]> git.saurik.com Git - apple/javascriptcore.git/blame - dfg/DFGValidate.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / dfg / DFGValidate.cpp
CommitLineData
93a37866 1/*
ed1e77d3 2 * Copyright (C) 2012-2015 Apple Inc. All rights reserved.
93a37866
A
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"
ed1e77d3 32#include "DFGMayExit.h"
81345200 33#include "JSCInlines.h"
93a37866
A
34#include <wtf/Assertions.h>
35#include <wtf/BitVector.h>
36
37namespace JSC { namespace DFG {
38
39class Validate {
40public:
ed1e77d3 41 Validate(Graph& graph, GraphDumpMode graphDumpMode, CString graphDumpBeforePhase)
93a37866
A
42 : m_graph(graph)
43 , m_graphDumpMode(graphDumpMode)
ed1e77d3 44 , m_graphDumpBeforePhase(graphDumpBeforePhase)
93a37866
A
45 {
46 }
47
48 #define VALIDATE(context, assertion) do { \
49 if (!(assertion)) { \
81345200 50 startCrashing(); \
93a37866
A
51 dataLogF("\n\n\nAt "); \
52 reportValidationContext context; \
ed1e77d3 53 dataLogF(": validation failed: %s (%s:%d).\n", #assertion, __FILE__, __LINE__); \
93a37866
A
54 dumpGraphIfAppropriate(); \
55 WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion); \
56 CRASH(); \
57 } \
58 } while (0)
59
60 #define V_EQUAL(context, left, right) do { \
61 if (left != right) { \
81345200 62 startCrashing(); \
93a37866
A
63 dataLogF("\n\n\nAt "); \
64 reportValidationContext context; \
ed1e77d3 65 dataLogF(": validation failed: (%s = ", #left); \
93a37866
A
66 dataLog(left); \
67 dataLogF(") == (%s = ", #right); \
68 dataLog(right); \
ed1e77d3 69 dataLogF(") (%s:%d).\n", __FILE__, __LINE__); \
93a37866
A
70 dumpGraphIfAppropriate(); \
71 WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #left " == " #right); \
72 CRASH(); \
73 } \
74 } while (0)
75
76 #define notSet (static_cast<size_t>(-1))
ed1e77d3 77
93a37866
A
78 void validate()
79 {
80 // NB. This code is not written for performance, since it is not intended to run
81 // in release builds.
81345200 82
93a37866 83 // Validate that all local variables at the head of the root block are dead.
81345200 84 BasicBlock* root = m_graph.block(0);
93a37866 85 for (unsigned i = 0; i < root->variablesAtHead.numberOfLocals(); ++i)
81345200 86 V_EQUAL((virtualRegisterForLocal(i), root), static_cast<Node*>(0), root->variablesAtHead.local(i));
93a37866
A
87
88 // Validate ref counts and uses.
81345200
A
89 for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
90 BasicBlock* block = m_graph.block(blockIndex);
91 if (!block)
93a37866 92 continue;
81345200 93 VALIDATE((block), block->isReachable);
93a37866 94 for (size_t i = 0; i < block->numNodes(); ++i)
81345200 95 m_myRefCounts.add(block->node(i), 0);
93a37866 96 }
81345200
A
97 for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
98 BasicBlock* block = m_graph.block(blockIndex);
99 if (!block)
93a37866
A
100 continue;
101 for (size_t i = 0; i < block->numNodes(); ++i) {
102 Node* node = block->node(i);
81345200 103 m_acceptableNodes.add(node);
93a37866
A
104 if (!node->shouldGenerate())
105 continue;
81345200
A
106 if (node->op() == Upsilon) {
107 VALIDATE((node), m_graph.m_form == SSA);
108 if (node->phi()->shouldGenerate())
109 m_myRefCounts.find(node)->value++;
110 }
93a37866
A
111 for (unsigned j = 0; j < m_graph.numChildren(node); ++j) {
112 // Phi children in LoadStore form are invalid.
113 if (m_graph.m_form == LoadStore && block->isPhiIndex(i))
114 continue;
115
116 Edge edge = m_graph.child(node, j);
117 if (!edge)
118 continue;
119
81345200 120 m_myRefCounts.find(edge.node())->value++;
ed1e77d3
A
121
122 validateEdgeWithDoubleResultIfNecessary(node, edge);
81345200
A
123 VALIDATE((node, edge), edge->hasInt52Result() == (edge.useKind() == Int52RepUse));
124
125 if (m_graph.m_form == SSA) {
126 // In SSA, all edges must hasResult().
127 VALIDATE((node, edge), edge->hasResult());
128 continue;
129 }
93a37866
A
130
131 // Unless I'm a Flush, Phantom, GetLocal, or Phi, my children should hasResult().
132 switch (node->op()) {
133 case Flush:
134 case GetLocal:
81345200 135 VALIDATE((node, edge), edge->hasVariableAccessData(m_graph));
93a37866
A
136 VALIDATE((node, edge), edge->variableAccessData() == node->variableAccessData());
137 break;
138 case PhantomLocal:
81345200 139 VALIDATE((node, edge), edge->hasVariableAccessData(m_graph));
93a37866
A
140 VALIDATE((node, edge), edge->variableAccessData() == node->variableAccessData());
141 VALIDATE((node, edge), edge->op() != SetLocal);
142 break;
143 case Phi:
81345200 144 VALIDATE((node, edge), edge->hasVariableAccessData(m_graph));
93a37866
A
145 if (m_graph.m_unificationState == LocallyUnified)
146 break;
147 VALIDATE((node, edge), edge->variableAccessData() == node->variableAccessData());
148 break;
93a37866
A
149 default:
150 VALIDATE((node, edge), edge->hasResult());
151 break;
152 }
153 }
154 }
155 }
81345200
A
156
157 for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
158 BasicBlock* block = m_graph.block(blockIndex);
159 if (!block)
160 continue;
161 for (size_t i = 0; i < block->numNodes(); ++i) {
162 Node* node = block->node(i);
163 if (m_graph.m_refCountState == ExactRefCount)
164 V_EQUAL((node), m_myRefCounts.get(node), node->adjustedRefCount());
81345200
A
165 }
166
ed1e77d3
A
167 bool foundTerminal = false;
168 for (size_t i = 0 ; i < block->size(); ++i) {
81345200 169 Node* node = block->at(i);
ed1e77d3
A
170 if (node->isTerminal()) {
171 foundTerminal = true;
172 for (size_t j = i + 1; j < block->size(); ++j) {
173 node = block->at(j);
174 VALIDATE((node), node->op() == Phantom || node->op() == PhantomLocal || node->op() == Flush || node->op() == Check);
175 m_graph.doToChildren(
176 node,
177 [&] (Edge edge) {
178 VALIDATE((node, edge), shouldNotHaveTypeCheck(edge.useKind()));
179 });
180 }
181 break;
182 }
81345200 183 }
ed1e77d3 184 VALIDATE((block), foundTerminal);
81345200
A
185
186 for (size_t i = 0; i < block->size(); ++i) {
187 Node* node = block->at(i);
188
ed1e77d3
A
189 VALIDATE((node), node->origin.semantic.isSet() == node->origin.forExit.isSet());
190 VALIDATE((node), !mayExit(m_graph, node) || node->origin.forExit.isSet());
191 VALIDATE((node), !node->hasStructure() || !!node->structure());
192 VALIDATE((node), !node->hasCellOperand() || node->cellOperand()->value().isCell());
193 VALIDATE((node), !node->hasCellOperand() || !!node->cellOperand()->value());
194
195 if (!(node->flags() & NodeHasVarArgs)) {
196 if (!node->child2())
197 VALIDATE((node), !node->child3());
198 if (!node->child1())
199 VALIDATE((node), !node->child2());
200 }
201
81345200
A
202 switch (node->op()) {
203 case Identity:
204 VALIDATE((node), canonicalResultRepresentation(node->result()) == canonicalResultRepresentation(node->child1()->result()));
205 break;
ed1e77d3
A
206 case SetLocal:
207 case PutStack:
208 case Upsilon:
209 VALIDATE((node), !!node->child1());
210 switch (node->child1().useKind()) {
211 case UntypedUse:
212 case CellUse:
213 case Int32Use:
214 case Int52RepUse:
215 case DoubleRepUse:
216 case BooleanUse:
217 break;
218 default:
219 VALIDATE((node), !"Bad use kind");
220 break;
221 }
222 break;
223 case MakeRope:
224 case ValueAdd:
225 case ArithAdd:
226 case ArithSub:
227 case ArithMul:
228 case ArithIMul:
229 case ArithDiv:
230 case ArithMod:
231 case ArithMin:
232 case ArithMax:
233 case ArithPow:
234 case CompareLess:
235 case CompareLessEq:
236 case CompareGreater:
237 case CompareGreaterEq:
238 case CompareEq:
239 case CompareEqConstant:
240 case CompareStrictEq:
241 VALIDATE((node), !!node->child1());
242 VALIDATE((node), !!node->child2());
243 break;
244 case PutStructure:
245 VALIDATE((node), !node->transition()->previous->dfgShouldWatch());
246 break;
247 case MultiPutByOffset:
248 for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
249 const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
250 if (variant.kind() != PutByIdVariant::Transition)
251 continue;
252 VALIDATE((node), !variant.oldStructureForTransition()->dfgShouldWatch());
253 }
254 break;
255 case DoubleConstant:
256 case Int52Constant:
257 VALIDATE((node), node->isNumberConstant());
258 break;
81345200
A
259 default:
260 break;
261 }
262 }
263 }
264
265 switch (m_graph.m_form) {
266 case LoadStore:
267 case ThreadedCPS:
268 validateCPS();
269 break;
270
271 case SSA:
272 validateSSA();
273 break;
274 }
275 }
276
277private:
278 Graph& m_graph;
279 GraphDumpMode m_graphDumpMode;
ed1e77d3 280 CString m_graphDumpBeforePhase;
81345200
A
281
282 HashMap<Node*, unsigned> m_myRefCounts;
283 HashSet<Node*> m_acceptableNodes;
284
285 void validateCPS()
286 {
287 for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
288 BasicBlock* block = m_graph.block(blockIndex);
289 if (!block)
93a37866
A
290 continue;
291
292 HashSet<Node*> phisInThisBlock;
293 HashSet<Node*> nodesInThisBlock;
294
295 for (size_t i = 0; i < block->numNodes(); ++i) {
296 Node* node = block->node(i);
297 nodesInThisBlock.add(node);
298 if (block->isPhiIndex(i))
299 phisInThisBlock.add(node);
93a37866
A
300 for (unsigned j = 0; j < m_graph.numChildren(node); ++j) {
301 Edge edge = m_graph.child(node, j);
302 if (!edge)
303 continue;
81345200 304 VALIDATE((node, edge), m_acceptableNodes.contains(edge.node()));
93a37866
A
305 }
306 }
307
308 for (size_t i = 0; i < block->phis.size(); ++i) {
309 Node* node = block->phis[i];
310 ASSERT(phisInThisBlock.contains(node));
311 VALIDATE((node), node->op() == Phi);
312 VirtualRegister local = node->local();
313 for (unsigned j = 0; j < m_graph.numChildren(node); ++j) {
314 // Phi children in LoadStore form are invalid.
315 if (m_graph.m_form == LoadStore && block->isPhiIndex(i))
316 continue;
317
318 Edge edge = m_graph.child(node, j);
319 if (!edge)
320 continue;
321
322 VALIDATE(
323 (node, edge),
324 edge->op() == SetLocal
325 || edge->op() == SetArgument
326 || edge->op() == Flush
81345200 327 || edge->op() == Phi);
93a37866
A
328
329 if (phisInThisBlock.contains(edge.node()))
330 continue;
331
332 if (nodesInThisBlock.contains(edge.node())) {
333 VALIDATE(
334 (node, edge),
335 edge->op() == SetLocal
93a37866
A
336 || edge->op() == SetArgument
337 || edge->op() == Flush);
338
339 continue;
340 }
341
342 // There must exist a predecessor block that has this node index in
343 // its tail variables.
344 bool found = false;
81345200
A
345 for (unsigned k = 0; k < block->predecessors.size(); ++k) {
346 BasicBlock* prevBlock = block->predecessors[k];
347 VALIDATE((block->predecessors[k]), prevBlock);
93a37866
A
348 Node* prevNode = prevBlock->variablesAtTail.operand(local);
349 // If we have a Phi that is not referring to *this* block then all predecessors
350 // must have that local available.
81345200 351 VALIDATE((local, block, block->predecessors[k]), prevNode);
93a37866
A
352 switch (prevNode->op()) {
353 case GetLocal:
354 case Flush:
355 case PhantomLocal:
356 prevNode = prevNode->child1().node();
357 break;
358 default:
359 break;
360 }
361 if (node->shouldGenerate()) {
81345200 362 VALIDATE((local, block->predecessors[k], prevNode),
93a37866
A
363 prevNode->shouldGenerate());
364 }
365 VALIDATE(
81345200 366 (local, block->predecessors[k], prevNode),
93a37866 367 prevNode->op() == SetLocal
93a37866
A
368 || prevNode->op() == SetArgument
369 || prevNode->op() == Phi);
370 if (prevNode == edge.node()) {
371 found = true;
372 break;
373 }
374 // At this point it cannot refer into this block.
81345200 375 VALIDATE((local, block->predecessors[k], prevNode), !prevBlock->isInBlock(edge.node()));
93a37866
A
376 }
377
378 VALIDATE((node, edge), found);
379 }
380 }
381
382 Operands<size_t> getLocalPositions(
383 block->variablesAtHead.numberOfArguments(),
384 block->variablesAtHead.numberOfLocals());
385 Operands<size_t> setLocalPositions(
386 block->variablesAtHead.numberOfArguments(),
387 block->variablesAtHead.numberOfLocals());
388
389 for (size_t i = 0; i < block->variablesAtHead.numberOfArguments(); ++i) {
81345200 390 VALIDATE((virtualRegisterForArgument(i), block), !block->variablesAtHead.argument(i) || block->variablesAtHead.argument(i)->hasVariableAccessData(m_graph));
93a37866 391 if (m_graph.m_form == ThreadedCPS)
81345200 392 VALIDATE((virtualRegisterForArgument(i), block), !block->variablesAtTail.argument(i) || block->variablesAtTail.argument(i)->hasVariableAccessData(m_graph));
93a37866
A
393
394 getLocalPositions.argument(i) = notSet;
395 setLocalPositions.argument(i) = notSet;
396 }
397 for (size_t i = 0; i < block->variablesAtHead.numberOfLocals(); ++i) {
81345200 398 VALIDATE((virtualRegisterForLocal(i), block), !block->variablesAtHead.local(i) || block->variablesAtHead.local(i)->hasVariableAccessData(m_graph));
93a37866 399 if (m_graph.m_form == ThreadedCPS)
81345200 400 VALIDATE((virtualRegisterForLocal(i), block), !block->variablesAtTail.local(i) || block->variablesAtTail.local(i)->hasVariableAccessData(m_graph));
93a37866
A
401
402 getLocalPositions.local(i) = notSet;
403 setLocalPositions.local(i) = notSet;
404 }
405
406 for (size_t i = 0; i < block->size(); ++i) {
407 Node* node = block->at(i);
408 ASSERT(nodesInThisBlock.contains(node));
409 VALIDATE((node), node->op() != Phi);
ed1e77d3 410 VALIDATE((node), node->origin.forExit.isSet());
93a37866
A
411 for (unsigned j = 0; j < m_graph.numChildren(node); ++j) {
412 Edge edge = m_graph.child(node, j);
413 if (!edge)
414 continue;
415 VALIDATE((node, edge), nodesInThisBlock.contains(edge.node()));
416 switch (node->op()) {
417 case PhantomLocal:
418 case GetLocal:
419 case Flush:
420 break;
93a37866
A
421 default:
422 VALIDATE((node, edge), !phisInThisBlock.contains(edge.node()));
423 break;
424 }
425 }
426
ed1e77d3
A
427 switch (node->op()) {
428 case Phi:
429 case Upsilon:
430 case CheckInBounds:
431 case PhantomNewObject:
432 case PhantomNewFunction:
433 case PhantomCreateActivation:
434 case GetMyArgumentByVal:
435 case PutHint:
436 case CheckStructureImmediate:
437 case MaterializeNewObject:
438 case MaterializeCreateActivation:
439 case PutStack:
440 case KillStack:
441 case GetStack:
442 VALIDATE((node), !"unexpected node type in CPS");
443 break;
444 case Phantom:
445 VALIDATE((node), m_graph.m_fixpointState != FixpointNotConverged);
446 break;
447 default:
448 break;
449 }
450
93a37866
A
451 if (!node->shouldGenerate())
452 continue;
453 switch (node->op()) {
454 case GetLocal:
93a37866
A
455 // Ignore GetLocal's that we know to be dead, but that the graph
456 // doesn't yet know to be dead.
81345200 457 if (!m_myRefCounts.get(node))
93a37866 458 break;
ed1e77d3 459 if (m_graph.m_form == ThreadedCPS) {
81345200 460 VALIDATE((node, block), getLocalPositions.operand(node->local()) == notSet);
ed1e77d3
A
461 VALIDATE((node, block), !!node->child1());
462 }
93a37866
A
463 getLocalPositions.operand(node->local()) = i;
464 break;
465 case SetLocal:
93a37866
A
466 // Only record the first SetLocal. There may be multiple SetLocals
467 // because of flushing.
468 if (setLocalPositions.operand(node->local()) != notSet)
469 break;
470 setLocalPositions.operand(node->local()) = i;
471 break;
ed1e77d3
A
472 case SetArgument:
473 // This acts like a reset. It's ok to have a second GetLocal for a local in the same
474 // block if we had a SetArgument for that local.
475 getLocalPositions.operand(node->local()) = notSet;
476 setLocalPositions.operand(node->local()) = notSet;
477 break;
93a37866
A
478 default:
479 break;
480 }
481 }
482
483 if (m_graph.m_form == LoadStore)
484 continue;
485
486 for (size_t i = 0; i < block->variablesAtHead.numberOfArguments(); ++i) {
487 checkOperand(
81345200 488 block, getLocalPositions, setLocalPositions, virtualRegisterForArgument(i));
93a37866
A
489 }
490 for (size_t i = 0; i < block->variablesAtHead.numberOfLocals(); ++i) {
491 checkOperand(
81345200 492 block, getLocalPositions, setLocalPositions, virtualRegisterForLocal(i));
93a37866
A
493 }
494 }
495 }
496
81345200
A
497 void validateSSA()
498 {
499 // FIXME: Add more things here.
500 // https://bugs.webkit.org/show_bug.cgi?id=123471
501
502 for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
503 BasicBlock* block = m_graph.block(blockIndex);
504 if (!block)
505 continue;
506
ed1e77d3
A
507 VALIDATE((block), block->phis.isEmpty());
508
81345200 509 unsigned nodeIndex = 0;
ed1e77d3 510 for (; nodeIndex < block->size() && !block->at(nodeIndex)->origin.forExit.isSet(); nodeIndex++) { }
81345200
A
511
512 VALIDATE((block), nodeIndex < block->size());
513
514 for (; nodeIndex < block->size(); nodeIndex++)
ed1e77d3 515 VALIDATE((block->at(nodeIndex)), block->at(nodeIndex)->origin.forExit.isSet());
81345200
A
516
517 for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
518 Node* node = block->at(nodeIndex);
519 switch (node->op()) {
520 case Phi:
ed1e77d3
A
521 VALIDATE((node), !node->origin.forExit.isSet());
522 break;
523
524 case GetLocal:
525 case SetLocal:
526 case GetLocalUnlinked:
527 case SetArgument:
528 case Phantom:
529 VALIDATE((node), !"bad node type for SSA");
81345200
A
530 break;
531
532 default:
533 // FIXME: Add more things here.
534 // https://bugs.webkit.org/show_bug.cgi?id=123471
535 break;
536 }
537 }
538 }
539 }
ed1e77d3
A
540
541 void validateEdgeWithDoubleResultIfNecessary(Node* node, Edge edge)
542 {
543 if (!edge->hasDoubleResult())
544 return;
545
546 if (m_graph.m_planStage < PlanStage::AfterFixup)
547 return;
548
549 VALIDATE((node, edge), edge.useKind() == DoubleRepUse || edge.useKind() == DoubleRepRealUse || edge.useKind() == DoubleRepMachineIntUse);
550 }
551
93a37866 552 void checkOperand(
81345200
A
553 BasicBlock* block, Operands<size_t>& getLocalPositions,
554 Operands<size_t>& setLocalPositions, VirtualRegister operand)
93a37866
A
555 {
556 if (getLocalPositions.operand(operand) == notSet)
557 return;
558 if (setLocalPositions.operand(operand) == notSet)
559 return;
560
93a37866
A
561 VALIDATE(
562 (block->at(getLocalPositions.operand(operand)),
563 block->at(setLocalPositions.operand(operand)),
81345200 564 block),
93a37866
A
565 getLocalPositions.operand(operand) < setLocalPositions.operand(operand));
566 }
567
568 void reportValidationContext(Node* node)
569 {
570 dataLogF("@%u", node->index());
571 }
572
81345200 573 void reportValidationContext(BasicBlock* block)
93a37866 574 {
81345200 575 dataLog("Block ", *block);
93a37866
A
576 }
577
578 void reportValidationContext(Node* node, Edge edge)
579 {
580 dataLog(node, " -> ", edge);
581 }
582
81345200 583 void reportValidationContext(VirtualRegister local, BasicBlock* block)
93a37866 584 {
81345200 585 if (!block) {
ed1e77d3 586 dataLog(local, " in null Block ");
81345200
A
587 return;
588 }
589
ed1e77d3 590 dataLog(local, " in Block ", *block);
93a37866
A
591 }
592
593 void reportValidationContext(
81345200 594 VirtualRegister local, BasicBlock* sourceBlock, BasicBlock* destinationBlock)
93a37866 595 {
ed1e77d3 596 dataLog(local, " in Block ", *sourceBlock, " -> ", *destinationBlock);
93a37866
A
597 }
598
599 void reportValidationContext(
81345200 600 VirtualRegister local, BasicBlock* sourceBlock, Node* prevNode)
93a37866 601 {
ed1e77d3 602 dataLog(prevNode, " for ", local, " in Block ", *sourceBlock);
93a37866
A
603 }
604
81345200 605 void reportValidationContext(Node* node, BasicBlock* block)
93a37866 606 {
81345200 607 dataLog(node, " in Block ", *block);
93a37866
A
608 }
609
81345200 610 void reportValidationContext(Node* node, Node* node2, BasicBlock* block)
93a37866 611 {
81345200 612 dataLog(node, " and ", node2, " in Block ", *block);
93a37866
A
613 }
614
615 void reportValidationContext(
81345200 616 Node* node, BasicBlock* block, Node* expectedNode, Edge incomingEdge)
93a37866 617 {
81345200 618 dataLog(node, " in Block ", *block, ", searching for ", expectedNode, " from ", incomingEdge);
93a37866
A
619 }
620
621 void dumpGraphIfAppropriate()
622 {
623 if (m_graphDumpMode == DontDumpGraph)
624 return;
ed1e77d3
A
625 dataLog("\n");
626 if (!m_graphDumpBeforePhase.isNull()) {
627 dataLog("Before phase:\n");
628 dataLog(m_graphDumpBeforePhase);
629 }
93a37866
A
630 dataLog("At time of failure:\n");
631 m_graph.dump();
632 }
633};
634
ed1e77d3 635void validate(Graph& graph, GraphDumpMode graphDumpMode, CString graphDumpBeforePhase)
93a37866 636{
ed1e77d3 637 Validate validationObject(graph, graphDumpMode, graphDumpBeforePhase);
93a37866
A
638 validationObject.validate();
639}
640
641} } // namespace JSC::DFG
642
643#endif // ENABLE(DFG_JIT)
644