cfa0a40c9b7a179274e0d6c87346696f31920f5d
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGGraph.cpp
1 /*
2  * Copyright (C) 2011, 2013, 2014 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 "DFGGraph.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "BytecodeLivenessAnalysisInlines.h"
32 #include "CodeBlock.h"
33 #include "CodeBlockWithJITType.h"
34 #include "DFGBlockWorklist.h"
35 #include "DFGClobberSet.h"
36 #include "DFGJITCode.h"
37 #include "DFGVariableAccessDataDump.h"
38 #include "FullBytecodeLiveness.h"
39 #include "FunctionExecutableDump.h"
40 #include "JIT.h"
41 #include "JSLexicalEnvironment.h"
42 #include "MaxFrameExtentForSlowPathCall.h"
43 #include "OperandsInlines.h"
44 #include "JSCInlines.h"
45 #include "StackAlignment.h"
46 #include <wtf/CommaPrinter.h>
47 #include <wtf/ListDump.h>
48
49 namespace JSC { namespace DFG {
50
51 // Creates an array of stringized names.
52 static const char* dfgOpNames[] = {
53 #define STRINGIZE_DFG_OP_ENUM(opcode, flags) #opcode ,
54     FOR_EACH_DFG_OP(STRINGIZE_DFG_OP_ENUM)
55 #undef STRINGIZE_DFG_OP_ENUM
56 };
57
58 Graph::Graph(VM& vm, Plan& plan, LongLivedState& longLivedState)
59     : m_vm(vm)
60     , m_plan(plan)
61     , m_codeBlock(m_plan.codeBlock.get())
62     , m_profiledBlock(m_codeBlock->alternative())
63     , m_allocator(longLivedState.m_allocator)
64     , m_mustHandleValues(OperandsLike, plan.mustHandleValues)
65     , m_hasArguments(false)
66     , m_nextMachineLocal(0)
67     , m_machineCaptureStart(std::numeric_limits<int>::max())
68     , m_fixpointState(BeforeFixpoint)
69     , m_structureRegistrationState(HaveNotStartedRegistering)
70     , m_form(LoadStore)
71     , m_unificationState(LocallyUnified)
72     , m_refCountState(EverythingIsLive)
73 {
74     ASSERT(m_profiledBlock);
75     
76     for (unsigned i = m_mustHandleValues.size(); i--;)
77         m_mustHandleValues[i] = freezeFragile(plan.mustHandleValues[i]);
78     
79     for (unsigned i = m_codeBlock->m_numVars; i--;) {
80         if (m_codeBlock->isCaptured(virtualRegisterForLocal(i)))
81             m_outermostCapturedVars.set(i);
82     }
83 }
84
85 Graph::~Graph()
86 {
87     for (BlockIndex blockIndex = numBlocks(); blockIndex--;) {
88         BasicBlock* block = this->block(blockIndex);
89         if (!block)
90             continue;
91
92         for (unsigned phiIndex = block->phis.size(); phiIndex--;)
93             m_allocator.free(block->phis[phiIndex]);
94         for (unsigned nodeIndex = block->size(); nodeIndex--;)
95             m_allocator.free(block->at(nodeIndex));
96     }
97     m_allocator.freeAll();
98 }
99
100 const char *Graph::opName(NodeType op)
101 {
102     return dfgOpNames[op];
103 }
104
105 static void printWhiteSpace(PrintStream& out, unsigned amount)
106 {
107     while (amount-- > 0)
108         out.print(" ");
109 }
110
111 bool Graph::dumpCodeOrigin(PrintStream& out, const char* prefix, Node* previousNode, Node* currentNode, DumpContext* context)
112 {
113     if (!previousNode)
114         return false;
115     
116     if (previousNode->origin.semantic.inlineCallFrame == currentNode->origin.semantic.inlineCallFrame)
117         return false;
118     
119     Vector<CodeOrigin> previousInlineStack = previousNode->origin.semantic.inlineStack();
120     Vector<CodeOrigin> currentInlineStack = currentNode->origin.semantic.inlineStack();
121     unsigned commonSize = std::min(previousInlineStack.size(), currentInlineStack.size());
122     unsigned indexOfDivergence = commonSize;
123     for (unsigned i = 0; i < commonSize; ++i) {
124         if (previousInlineStack[i].inlineCallFrame != currentInlineStack[i].inlineCallFrame) {
125             indexOfDivergence = i;
126             break;
127         }
128     }
129     
130     bool hasPrinted = false;
131     
132     // Print the pops.
133     for (unsigned i = previousInlineStack.size(); i-- > indexOfDivergence;) {
134         out.print(prefix);
135         printWhiteSpace(out, i * 2);
136         out.print("<-- ", inContext(*previousInlineStack[i].inlineCallFrame, context), "\n");
137         hasPrinted = true;
138     }
139     
140     // Print the pushes.
141     for (unsigned i = indexOfDivergence; i < currentInlineStack.size(); ++i) {
142         out.print(prefix);
143         printWhiteSpace(out, i * 2);
144         out.print("--> ", inContext(*currentInlineStack[i].inlineCallFrame, context), "\n");
145         hasPrinted = true;
146     }
147     
148     return hasPrinted;
149 }
150
151 int Graph::amountOfNodeWhiteSpace(Node* node)
152 {
153     return (node->origin.semantic.inlineDepth() - 1) * 2;
154 }
155
156 void Graph::printNodeWhiteSpace(PrintStream& out, Node* node)
157 {
158     printWhiteSpace(out, amountOfNodeWhiteSpace(node));
159 }
160
161 void Graph::dump(PrintStream& out, const char* prefix, Node* node, DumpContext* context)
162 {
163     NodeType op = node->op();
164
165     unsigned refCount = node->refCount();
166     bool mustGenerate = node->mustGenerate();
167     if (mustGenerate)
168         --refCount;
169
170     out.print(prefix);
171     printNodeWhiteSpace(out, node);
172
173     // Example/explanation of dataflow dump output
174     //
175     //   14:   <!2:7>  GetByVal(@3, @13)
176     //   ^1     ^2 ^3     ^4       ^5
177     //
178     // (1) The nodeIndex of this operation.
179     // (2) The reference count. The number printed is the 'real' count,
180     //     not including the 'mustGenerate' ref. If the node is
181     //     'mustGenerate' then the count it prefixed with '!'.
182     // (3) The virtual register slot assigned to this node.
183     // (4) The name of the operation.
184     // (5) The arguments to the operation. The may be of the form:
185     //         @#   - a NodeIndex referencing a prior node in the graph.
186     //         arg# - an argument number.
187     //         id#  - the index in the CodeBlock of an identifier { if codeBlock is passed to dump(), the string representation is displayed }.
188     //         var# - the index of a var on the global object, used by GetGlobalVar/PutGlobalVar operations.
189     out.printf("% 4d:<%c%u:", (int)node->index(), mustGenerate ? '!' : ' ', refCount);
190     if (node->hasResult() && node->hasVirtualRegister() && node->virtualRegister().isValid())
191         out.print(node->virtualRegister());
192     else
193         out.print("-");
194     out.print(">\t", opName(op), "(");
195     CommaPrinter comma;
196     if (node->flags() & NodeHasVarArgs) {
197         for (unsigned childIdx = node->firstChild(); childIdx < node->firstChild() + node->numChildren(); childIdx++) {
198             if (!m_varArgChildren[childIdx])
199                 continue;
200             out.print(comma, m_varArgChildren[childIdx]);
201         }
202     } else {
203         if (!!node->child1() || !!node->child2() || !!node->child3())
204             out.print(comma, node->child1());
205         if (!!node->child2() || !!node->child3())
206             out.print(comma, node->child2());
207         if (!!node->child3())
208             out.print(comma, node->child3());
209     }
210
211     if (toCString(NodeFlagsDump(node->flags())) != "<empty>")
212         out.print(comma, NodeFlagsDump(node->flags()));
213     if (node->prediction())
214         out.print(comma, SpeculationDump(node->prediction()));
215     if (node->hasArrayMode())
216         out.print(comma, node->arrayMode());
217     if (node->hasArithMode())
218         out.print(comma, node->arithMode());
219     if (node->hasVarNumber())
220         out.print(comma, node->varNumber());
221     if (node->hasRegisterPointer())
222         out.print(comma, "global", globalObjectFor(node->origin.semantic)->findRegisterIndex(node->registerPointer()), "(", RawPointer(node->registerPointer()), ")");
223     if (node->hasIdentifier())
224         out.print(comma, "id", node->identifierNumber(), "{", identifiers()[node->identifierNumber()], "}");
225     if (node->hasStructureSet())
226         out.print(comma, inContext(node->structureSet(), context));
227     if (node->hasStructure())
228         out.print(comma, inContext(*node->structure(), context));
229     if (node->hasTransition())
230         out.print(comma, pointerDumpInContext(node->transition(), context));
231     if (node->hasCellOperand()) {
232         if (!node->cellOperand()->value() || !node->cellOperand()->value().isCell())
233             out.print(comma, "invalid cell operand: ", node->cellOperand()->value());
234         else {
235             out.print(comma, pointerDump(node->cellOperand()->value().asCell()));
236             if (node->cellOperand()->value().isCell()) {
237                 CallVariant variant(node->cellOperand()->value().asCell());
238                 if (ExecutableBase* executable = variant.executable()) {
239                     if (executable->isHostFunction())
240                         out.print(comma, "<host function>");
241                     else if (FunctionExecutable* functionExecutable = jsDynamicCast<FunctionExecutable*>(executable))
242                         out.print(comma, FunctionExecutableDump(functionExecutable));
243                     else
244                         out.print(comma, "<non-function executable>");
245                 }
246             }
247         }
248     }
249     if (node->hasFunctionDeclIndex()) {
250         FunctionExecutable* executable = m_codeBlock->functionDecl(node->functionDeclIndex());
251         out.print(comma, FunctionExecutableDump(executable));
252     }
253     if (node->hasFunctionExprIndex()) {
254         FunctionExecutable* executable = m_codeBlock->functionExpr(node->functionExprIndex());
255         out.print(comma, FunctionExecutableDump(executable));
256     }
257     if (node->hasStorageAccessData()) {
258         StorageAccessData& storageAccessData = node->storageAccessData();
259         out.print(comma, "id", storageAccessData.identifierNumber, "{", identifiers()[storageAccessData.identifierNumber], "}");
260         out.print(", ", static_cast<ptrdiff_t>(storageAccessData.offset));
261     }
262     if (node->hasMultiGetByOffsetData()) {
263         MultiGetByOffsetData& data = node->multiGetByOffsetData();
264         out.print(comma, "id", data.identifierNumber, "{", identifiers()[data.identifierNumber], "}");
265         for (unsigned i = 0; i < data.variants.size(); ++i)
266             out.print(comma, inContext(data.variants[i], context));
267     }
268     if (node->hasMultiPutByOffsetData()) {
269         MultiPutByOffsetData& data = node->multiPutByOffsetData();
270         out.print(comma, "id", data.identifierNumber, "{", identifiers()[data.identifierNumber], "}");
271         for (unsigned i = 0; i < data.variants.size(); ++i)
272             out.print(comma, inContext(data.variants[i], context));
273     }
274     ASSERT(node->hasVariableAccessData(*this) == node->hasLocal(*this));
275     if (node->hasVariableAccessData(*this)) {
276         VariableAccessData* variableAccessData = node->tryGetVariableAccessData();
277         if (variableAccessData) {
278             VirtualRegister operand = variableAccessData->local();
279             if (operand.isArgument())
280                 out.print(comma, "arg", operand.toArgument(), "(", VariableAccessDataDump(*this, variableAccessData), ")");
281             else
282                 out.print(comma, "loc", operand.toLocal(), "(", VariableAccessDataDump(*this, variableAccessData), ")");
283             
284             operand = variableAccessData->machineLocal();
285             if (operand.isValid()) {
286                 if (operand.isArgument())
287                     out.print(comma, "machine:arg", operand.toArgument());
288                 else
289                     out.print(comma, "machine:loc", operand.toLocal());
290             }
291         }
292     }
293     if (node->hasUnlinkedLocal()) {
294         VirtualRegister operand = node->unlinkedLocal();
295         if (operand.isArgument())
296             out.print(comma, "arg", operand.toArgument());
297         else
298             out.print(comma, "loc", operand.toLocal());
299     }
300     if (node->hasUnlinkedMachineLocal()) {
301         VirtualRegister operand = node->unlinkedMachineLocal();
302         if (operand.isValid()) {
303             if (operand.isArgument())
304                 out.print(comma, "machine:arg", operand.toArgument());
305             else
306                 out.print(comma, "machine:loc", operand.toLocal());
307         }
308     }
309     if (node->hasConstantBuffer()) {
310         out.print(comma);
311         out.print(node->startConstant(), ":[");
312         CommaPrinter anotherComma;
313         for (unsigned i = 0; i < node->numConstants(); ++i)
314             out.print(anotherComma, pointerDumpInContext(freeze(m_codeBlock->constantBuffer(node->startConstant())[i]), context));
315         out.print("]");
316     }
317     if (node->hasIndexingType())
318         out.print(comma, IndexingTypeDump(node->indexingType()));
319     if (node->hasTypedArrayType())
320         out.print(comma, node->typedArrayType());
321     if (node->hasPhi())
322         out.print(comma, "^", node->phi()->index());
323     if (node->hasExecutionCounter())
324         out.print(comma, RawPointer(node->executionCounter()));
325     if (node->hasVariableWatchpointSet())
326         out.print(comma, RawPointer(node->variableWatchpointSet()));
327     if (node->hasTypedArray())
328         out.print(comma, inContext(JSValue(node->typedArray()), context));
329     if (node->hasStoragePointer())
330         out.print(comma, RawPointer(node->storagePointer()));
331     if (node->hasObjectMaterializationData())
332         out.print(comma, node->objectMaterializationData());
333     if (node->isConstant())
334         out.print(comma, pointerDumpInContext(node->constant(), context));
335     if (node->isJump())
336         out.print(comma, "T:", *node->targetBlock());
337     if (node->isBranch())
338         out.print(comma, "T:", node->branchData()->taken, ", F:", node->branchData()->notTaken);
339     if (node->isSwitch()) {
340         SwitchData* data = node->switchData();
341         out.print(comma, data->kind);
342         for (unsigned i = 0; i < data->cases.size(); ++i)
343             out.print(comma, inContext(data->cases[i].value, context), ":", data->cases[i].target);
344         out.print(comma, "default:", data->fallThrough);
345     }
346     ClobberSet reads;
347     ClobberSet writes;
348     addReadsAndWrites(*this, node, reads, writes);
349     if (!reads.isEmpty())
350         out.print(comma, "R:", sortedListDump(reads.direct(), ","));
351     if (!writes.isEmpty())
352         out.print(comma, "W:", sortedListDump(writes.direct(), ","));
353     if (node->origin.isSet()) {
354         out.print(comma, "bc#", node->origin.semantic.bytecodeIndex);
355         if (node->origin.semantic != node->origin.forExit)
356             out.print(comma, "exit: ", node->origin.forExit);
357     }
358     
359     out.print(")");
360
361     if (node->hasVariableAccessData(*this) && node->tryGetVariableAccessData())
362         out.print("  predicting ", SpeculationDump(node->tryGetVariableAccessData()->prediction()));
363     else if (node->hasHeapPrediction())
364         out.print("  predicting ", SpeculationDump(node->getHeapPrediction()));
365     
366     out.print("\n");
367 }
368
369 void Graph::dumpBlockHeader(PrintStream& out, const char* prefix, BasicBlock* block, PhiNodeDumpMode phiNodeDumpMode, DumpContext* context)
370 {
371     out.print(prefix, "Block ", *block, " (", inContext(block->at(0)->origin.semantic, context), "):", block->isReachable ? "" : " (skipped)", block->isOSRTarget ? " (OSR target)" : "", "\n");
372     if (block->executionCount == block->executionCount)
373         out.print(prefix, "  Execution count: ", block->executionCount, "\n");
374     out.print(prefix, "  Predecessors:");
375     for (size_t i = 0; i < block->predecessors.size(); ++i)
376         out.print(" ", *block->predecessors[i]);
377     out.print("\n");
378     out.print(prefix, "  Successors:");
379     for (BasicBlock* successor : block->successors()) {
380         out.print(" ", *successor);
381         if (m_prePostNumbering.isValid())
382             out.print(" (", m_prePostNumbering.edgeKind(block, successor), ")");
383     }
384     out.print("\n");
385     if (m_dominators.isValid()) {
386         out.print(prefix, "  Dominated by: ", m_dominators.dominatorsOf(block), "\n");
387         out.print(prefix, "  Dominates: ", m_dominators.blocksDominatedBy(block), "\n");
388         out.print(prefix, "  Dominance Frontier: ", m_dominators.dominanceFrontierOf(block), "\n");
389         out.print(prefix, "  Iterated Dominance Frontier: ", m_dominators.iteratedDominanceFrontierOf(BlockList(1, block)), "\n");
390     }
391     if (m_prePostNumbering.isValid())
392         out.print(prefix, "  Pre/Post Numbering: ", m_prePostNumbering.preNumber(block), "/", m_prePostNumbering.postNumber(block), "\n");
393     if (m_naturalLoops.isValid()) {
394         if (const NaturalLoop* loop = m_naturalLoops.headerOf(block)) {
395             out.print(prefix, "  Loop header, contains:");
396             Vector<BlockIndex> sortedBlockList;
397             for (unsigned i = 0; i < loop->size(); ++i)
398                 sortedBlockList.append(loop->at(i)->index);
399             std::sort(sortedBlockList.begin(), sortedBlockList.end());
400             for (unsigned i = 0; i < sortedBlockList.size(); ++i)
401                 out.print(" #", sortedBlockList[i]);
402             out.print("\n");
403         }
404         
405         Vector<const NaturalLoop*> containingLoops =
406             m_naturalLoops.loopsOf(block);
407         if (!containingLoops.isEmpty()) {
408             out.print(prefix, "  Containing loop headers:");
409             for (unsigned i = 0; i < containingLoops.size(); ++i)
410                 out.print(" ", *containingLoops[i]->header());
411             out.print("\n");
412         }
413     }
414     if (!block->phis.isEmpty()) {
415         out.print(prefix, "  Phi Nodes:");
416         for (size_t i = 0; i < block->phis.size(); ++i) {
417             Node* phiNode = block->phis[i];
418             if (!phiNode->shouldGenerate() && phiNodeDumpMode == DumpLivePhisOnly)
419                 continue;
420             out.print(" @", phiNode->index(), "<", phiNode->refCount(), ">->(");
421             if (phiNode->child1()) {
422                 out.print("@", phiNode->child1()->index());
423                 if (phiNode->child2()) {
424                     out.print(", @", phiNode->child2()->index());
425                     if (phiNode->child3())
426                         out.print(", @", phiNode->child3()->index());
427                 }
428             }
429             out.print(")", i + 1 < block->phis.size() ? "," : "");
430         }
431         out.print("\n");
432     }
433 }
434
435 void Graph::dump(PrintStream& out, DumpContext* context)
436 {
437     DumpContext myContext;
438     myContext.graph = this;
439     if (!context)
440         context = &myContext;
441     
442     out.print("\n");
443     out.print("DFG for ", CodeBlockWithJITType(m_codeBlock, JITCode::DFGJIT), ":\n");
444     out.print("  Fixpoint state: ", m_fixpointState, "; Form: ", m_form, "; Unification state: ", m_unificationState, "; Ref count state: ", m_refCountState, "\n");
445     out.print("\n");
446     
447     Node* lastNode = 0;
448     for (size_t b = 0; b < m_blocks.size(); ++b) {
449         BasicBlock* block = m_blocks[b].get();
450         if (!block)
451             continue;
452         dumpBlockHeader(out, "", block, DumpAllPhis, context);
453         out.print("  States: ", block->cfaStructureClobberStateAtHead);
454         if (!block->cfaHasVisited)
455             out.print(", CurrentlyCFAUnreachable");
456         if (!block->intersectionOfCFAHasVisited)
457             out.print(", CFAUnreachable");
458         out.print("\n");
459         switch (m_form) {
460         case LoadStore:
461         case ThreadedCPS: {
462             out.print("  Vars Before: ");
463             if (block->cfaHasVisited)
464                 out.print(inContext(block->valuesAtHead, context));
465             else
466                 out.print("<empty>");
467             out.print("\n");
468             out.print("  Intersected Vars Before: ");
469             if (block->intersectionOfCFAHasVisited)
470                 out.print(inContext(block->intersectionOfPastValuesAtHead, context));
471             else
472                 out.print("<empty>");
473             out.print("\n");
474             out.print("  Var Links: ", block->variablesAtHead, "\n");
475             break;
476         }
477             
478         case SSA: {
479             RELEASE_ASSERT(block->ssa);
480             out.print("  Availability: ", block->ssa->availabilityAtHead, "\n");
481             out.print("  Live: ", nodeListDump(block->ssa->liveAtHead), "\n");
482             out.print("  Values: ", nodeMapDump(block->ssa->valuesAtHead, context), "\n");
483             break;
484         } }
485         for (size_t i = 0; i < block->size(); ++i) {
486             dumpCodeOrigin(out, "", lastNode, block->at(i), context);
487             dump(out, "", block->at(i), context);
488             lastNode = block->at(i);
489         }
490         out.print("  States: ", block->cfaBranchDirection, ", ", block->cfaStructureClobberStateAtTail);
491         if (!block->cfaDidFinish)
492             out.print(", CFAInvalidated");
493         out.print("\n");
494         switch (m_form) {
495         case LoadStore:
496         case ThreadedCPS: {
497             out.print("  Vars After: ");
498             if (block->cfaHasVisited)
499                 out.print(inContext(block->valuesAtTail, context));
500             else
501                 out.print("<empty>");
502             out.print("\n");
503             out.print("  Var Links: ", block->variablesAtTail, "\n");
504             break;
505         }
506             
507         case SSA: {
508             RELEASE_ASSERT(block->ssa);
509             out.print("  Availability: ", block->ssa->availabilityAtTail, "\n");
510             out.print("  Live: ", nodeListDump(block->ssa->liveAtTail), "\n");
511             out.print("  Values: ", nodeMapDump(block->ssa->valuesAtTail, context), "\n");
512             break;
513         } }
514         out.print("\n");
515     }
516     
517     if (!myContext.isEmpty()) {
518         myContext.dump(out);
519         out.print("\n");
520     }
521 }
522
523 void Graph::dethread()
524 {
525     if (m_form == LoadStore || m_form == SSA)
526         return;
527     
528     if (logCompilationChanges())
529         dataLog("Dethreading DFG graph.\n");
530     
531     SamplingRegion samplingRegion("DFG Dethreading");
532     
533     for (BlockIndex blockIndex = m_blocks.size(); blockIndex--;) {
534         BasicBlock* block = m_blocks[blockIndex].get();
535         if (!block)
536             continue;
537         for (unsigned phiIndex = block->phis.size(); phiIndex--;) {
538             Node* phi = block->phis[phiIndex];
539             phi->children.reset();
540         }
541     }
542     
543     m_form = LoadStore;
544 }
545
546 void Graph::handleSuccessor(Vector<BasicBlock*, 16>& worklist, BasicBlock* block, BasicBlock* successor)
547 {
548     if (!successor->isReachable) {
549         successor->isReachable = true;
550         worklist.append(successor);
551     }
552     
553     successor->predecessors.append(block);
554 }
555
556 void Graph::determineReachability()
557 {
558     Vector<BasicBlock*, 16> worklist;
559     worklist.append(block(0));
560     block(0)->isReachable = true;
561     while (!worklist.isEmpty()) {
562         BasicBlock* block = worklist.takeLast();
563         for (unsigned i = block->numSuccessors(); i--;)
564             handleSuccessor(worklist, block, block->successor(i));
565     }
566 }
567
568 void Graph::resetReachability()
569 {
570     for (BlockIndex blockIndex = m_blocks.size(); blockIndex--;) {
571         BasicBlock* block = m_blocks[blockIndex].get();
572         if (!block)
573             continue;
574         block->isReachable = false;
575         block->predecessors.clear();
576     }
577     
578     determineReachability();
579 }
580
581 void Graph::mergeRelevantToOSR()
582 {
583     for (BasicBlock* block : blocksInNaturalOrder()) {
584         for (Node* node : *block) {
585             switch (node->op()) {
586             case MovHint:
587                 node->child1()->mergeFlags(NodeRelevantToOSR);
588                 break;
589                 
590             case PutStructureHint:
591             case PutByOffsetHint:
592                 node->child2()->mergeFlags(NodeRelevantToOSR);
593                 break;
594                 
595             default:
596                 break;
597             }
598         }
599     }
600 }
601
602 namespace {
603
604 class RefCountCalculator {
605 public:
606     RefCountCalculator(Graph& graph)
607         : m_graph(graph)
608     {
609     }
610     
611     void calculate()
612     {
613         // First reset the counts to 0 for all nodes.
614         //
615         // Also take this opportunity to pretend that Check nodes are not NodeMustGenerate. Check
616         // nodes are MustGenerate because they are executed for effect, but they follow the same
617         // DCE rules as nodes that aren't MustGenerate: they only contribute to the ref count of
618         // their children if the edges require checks. Non-checking edges are removed. Note that
619         // for any Checks left over, this phase will turn them back into NodeMustGenerate.
620         for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
621             BasicBlock* block = m_graph.block(blockIndex);
622             if (!block)
623                 continue;
624             for (unsigned indexInBlock = block->size(); indexInBlock--;)
625                 block->at(indexInBlock)->setRefCount(0);
626             for (unsigned phiIndex = block->phis.size(); phiIndex--;)
627                 block->phis[phiIndex]->setRefCount(0);
628         }
629     
630         // Now find the roots:
631         // - Nodes that are must-generate.
632         // - Nodes that are reachable from type checks.
633         // Set their ref counts to 1 and put them on the worklist.
634         for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
635             BasicBlock* block = m_graph.block(blockIndex);
636             if (!block)
637                 continue;
638             for (unsigned indexInBlock = block->size(); indexInBlock--;) {
639                 Node* node = block->at(indexInBlock);
640                 DFG_NODE_DO_TO_CHILDREN(m_graph, node, findTypeCheckRoot);
641                 if (!(node->flags() & NodeMustGenerate))
642                     continue;
643                 if (node->op() == Check) {
644                     // We don't treat Check nodes as MustGenerate. We will gladly
645                     // kill them off in this phase.
646                     continue;
647                 }
648                 if (!node->postfixRef())
649                     m_worklist.append(node);
650             }
651         }
652         
653         while (!m_worklist.isEmpty()) {
654             while (!m_worklist.isEmpty()) {
655                 Node* node = m_worklist.last();
656                 m_worklist.removeLast();
657                 ASSERT(node->shouldGenerate()); // It should not be on the worklist unless it's ref'ed.
658                 DFG_NODE_DO_TO_CHILDREN(m_graph, node, countEdge);
659             }
660             
661             if (m_graph.m_form == SSA) {
662                 // Find Phi->Upsilon edges, which are represented as meta-data in the
663                 // Upsilon.
664                 for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
665                     BasicBlock* block = m_graph.block(blockIndex);
666                     if (!block)
667                         continue;
668                     for (unsigned nodeIndex = block->size(); nodeIndex--;) {
669                         Node* node = block->at(nodeIndex);
670                         if (node->op() != Upsilon)
671                             continue;
672                         if (node->shouldGenerate())
673                             continue;
674                         if (node->phi()->shouldGenerate())
675                             countNode(node);
676                     }
677                 }
678             }
679         }
680     }
681     
682 private:
683     void findTypeCheckRoot(Node*, Edge edge)
684     {
685         // We may have an "unproved" untyped use for code that is unreachable. The CFA
686         // will just not have gotten around to it.
687         if (edge.isProved() || edge.willNotHaveCheck())
688             return;
689         if (!edge->postfixRef())
690             m_worklist.append(edge.node());
691     }
692     
693     void countNode(Node* node)
694     {
695         if (node->postfixRef())
696             return;
697         m_worklist.append(node);
698     }
699     
700     void countEdge(Node*, Edge edge)
701     {
702         // Don't count edges that are already counted for their type checks.
703         if (!(edge.isProved() || edge.willNotHaveCheck()))
704             return;
705         countNode(edge.node());
706     }
707     
708     Graph& m_graph;
709     Vector<Node*, 128> m_worklist;
710 };
711
712 } // anonymous namespace
713
714 void Graph::computeRefCounts()
715 {
716     RefCountCalculator calculator(*this);
717     calculator.calculate();
718 }
719
720 void Graph::killBlockAndItsContents(BasicBlock* block)
721 {
722     for (unsigned phiIndex = block->phis.size(); phiIndex--;)
723         m_allocator.free(block->phis[phiIndex]);
724     for (unsigned nodeIndex = block->size(); nodeIndex--;)
725         m_allocator.free(block->at(nodeIndex));
726     
727     killBlock(block);
728 }
729
730 void Graph::killUnreachableBlocks()
731 {
732     for (BlockIndex blockIndex = 0; blockIndex < numBlocks(); ++blockIndex) {
733         BasicBlock* block = this->block(blockIndex);
734         if (!block)
735             continue;
736         if (block->isReachable)
737             continue;
738         
739         killBlockAndItsContents(block);
740     }
741 }
742
743 void Graph::invalidateCFG()
744 {
745     m_dominators.invalidate();
746     m_naturalLoops.invalidate();
747     m_prePostNumbering.invalidate();
748 }
749
750 void Graph::substituteGetLocal(BasicBlock& block, unsigned startIndexInBlock, VariableAccessData* variableAccessData, Node* newGetLocal)
751 {
752     if (variableAccessData->isCaptured()) {
753         // Let CSE worry about this one.
754         return;
755     }
756     for (unsigned indexInBlock = startIndexInBlock; indexInBlock < block.size(); ++indexInBlock) {
757         Node* node = block[indexInBlock];
758         bool shouldContinue = true;
759         switch (node->op()) {
760         case SetLocal: {
761             if (node->local() == variableAccessData->local())
762                 shouldContinue = false;
763             break;
764         }
765                 
766         case GetLocal: {
767             if (node->variableAccessData() != variableAccessData)
768                 continue;
769             substitute(block, indexInBlock, node, newGetLocal);
770             Node* oldTailNode = block.variablesAtTail.operand(variableAccessData->local());
771             if (oldTailNode == node)
772                 block.variablesAtTail.operand(variableAccessData->local()) = newGetLocal;
773             shouldContinue = false;
774             break;
775         }
776                 
777         default:
778             break;
779         }
780         if (!shouldContinue)
781             break;
782     }
783 }
784
785 BlockList Graph::blocksInPreOrder()
786 {
787     BlockList result;
788     BlockWorklist worklist;
789     worklist.push(block(0));
790     while (BasicBlock* block = worklist.pop()) {
791         result.append(block);
792         for (unsigned i = block->numSuccessors(); i--;)
793             worklist.push(block->successor(i));
794     }
795     return result;
796 }
797
798 BlockList Graph::blocksInPostOrder()
799 {
800     BlockList result;
801     PostOrderBlockWorklist worklist;
802     worklist.push(block(0));
803     while (BlockWithOrder item = worklist.pop()) {
804         switch (item.order) {
805         case PreOrder:
806             worklist.pushPost(item.block);
807             for (unsigned i = item.block->numSuccessors(); i--;)
808                 worklist.push(item.block->successor(i));
809             break;
810         case PostOrder:
811             result.append(item.block);
812             break;
813         }
814     }
815     return result;
816 }
817
818 void Graph::clearReplacements()
819 {
820     for (BlockIndex blockIndex = numBlocks(); blockIndex--;) {
821         BasicBlock* block = m_blocks[blockIndex].get();
822         if (!block)
823             continue;
824         for (unsigned phiIndex = block->phis.size(); phiIndex--;)
825             block->phis[phiIndex]->replacement = 0;
826         for (unsigned nodeIndex = block->size(); nodeIndex--;)
827             block->at(nodeIndex)->replacement = 0;
828     }
829 }
830
831 void Graph::initializeNodeOwners()
832 {
833     for (BlockIndex blockIndex = numBlocks(); blockIndex--;) {
834         BasicBlock* block = m_blocks[blockIndex].get();
835         if (!block)
836             continue;
837         for (unsigned phiIndex = block->phis.size(); phiIndex--;)
838             block->phis[phiIndex]->owner = block;
839         for (unsigned nodeIndex = block->size(); nodeIndex--;)
840             block->at(nodeIndex)->owner = block;
841     }
842 }
843
844 void Graph::clearFlagsOnAllNodes(NodeFlags flags)
845 {
846     for (BlockIndex blockIndex = numBlocks(); blockIndex--;) {
847         BasicBlock* block = m_blocks[blockIndex].get();
848         if (!block)
849             continue;
850         for (unsigned phiIndex = block->phis.size(); phiIndex--;)
851             block->phis[phiIndex]->clearFlags(flags);
852         for (unsigned nodeIndex = block->size(); nodeIndex--;)
853             block->at(nodeIndex)->clearFlags(flags);
854     }
855 }
856
857 FullBytecodeLiveness& Graph::livenessFor(CodeBlock* codeBlock)
858 {
859     HashMap<CodeBlock*, std::unique_ptr<FullBytecodeLiveness>>::iterator iter = m_bytecodeLiveness.find(codeBlock);
860     if (iter != m_bytecodeLiveness.end())
861         return *iter->value;
862     
863     std::unique_ptr<FullBytecodeLiveness> liveness = std::make_unique<FullBytecodeLiveness>();
864     codeBlock->livenessAnalysis().computeFullLiveness(*liveness);
865     FullBytecodeLiveness& result = *liveness;
866     m_bytecodeLiveness.add(codeBlock, WTF::move(liveness));
867     return result;
868 }
869
870 FullBytecodeLiveness& Graph::livenessFor(InlineCallFrame* inlineCallFrame)
871 {
872     return livenessFor(baselineCodeBlockFor(inlineCallFrame));
873 }
874
875 bool Graph::isLiveInBytecode(VirtualRegister operand, CodeOrigin codeOrigin)
876 {
877     for (;;) {
878         VirtualRegister reg = VirtualRegister(
879             operand.offset() - codeOrigin.stackOffset());
880         
881         if (operand.offset() < codeOrigin.stackOffset() + JSStack::CallFrameHeaderSize) {
882             if (reg.isArgument()) {
883                 RELEASE_ASSERT(reg.offset() < JSStack::CallFrameHeaderSize);
884                 
885                 if (!codeOrigin.inlineCallFrame->isClosureCall)
886                     return false;
887                 
888                 if (reg.offset() == JSStack::Callee)
889                     return true;
890                 if (reg.offset() == JSStack::ScopeChain)
891                     return true;
892                 
893                 return false;
894             }
895             
896             return livenessFor(codeOrigin.inlineCallFrame).operandIsLive(
897                 reg.offset(), codeOrigin.bytecodeIndex);
898         }
899         
900         InlineCallFrame* inlineCallFrame = codeOrigin.inlineCallFrame;
901         if (!inlineCallFrame)
902             break;
903
904         // Arguments are always live. This would be redundant if it wasn't for our
905         // op_call_varargs inlining.
906         // FIXME: 'this' might not be live, but we don't have a way of knowing.
907         // https://bugs.webkit.org/show_bug.cgi?id=128519
908         if (reg.isArgument()
909             && static_cast<size_t>(reg.toArgument()) < inlineCallFrame->arguments.size())
910             return true;
911         
912         codeOrigin = inlineCallFrame->caller;
913     }
914     
915     return true;
916 }
917
918 unsigned Graph::frameRegisterCount()
919 {
920     unsigned result = m_nextMachineLocal + std::max(m_parameterSlots, static_cast<unsigned>(maxFrameExtentForSlowPathCallInRegisters));
921     return roundLocalRegisterCountForFramePointerOffset(result);
922 }
923
924 unsigned Graph::stackPointerOffset()
925 {
926     return virtualRegisterForLocal(frameRegisterCount() - 1).offset();
927 }
928
929 unsigned Graph::requiredRegisterCountForExit()
930 {
931     unsigned count = JIT::frameRegisterCountFor(m_profiledBlock);
932     for (InlineCallFrameSet::iterator iter = m_plan.inlineCallFrames->begin(); !!iter; ++iter) {
933         InlineCallFrame* inlineCallFrame = *iter;
934         CodeBlock* codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame);
935         unsigned requiredCount = VirtualRegister(inlineCallFrame->stackOffset).toLocal() + 1 + JIT::frameRegisterCountFor(codeBlock);
936         count = std::max(count, requiredCount);
937     }
938     return count;
939 }
940
941 unsigned Graph::requiredRegisterCountForExecutionAndExit()
942 {
943     return std::max(frameRegisterCount(), requiredRegisterCountForExit());
944 }
945
946 JSValue Graph::tryGetConstantProperty(
947     JSValue base, const StructureSet& structureSet, PropertyOffset offset)
948 {
949     if (!base || !base.isObject())
950         return JSValue();
951     
952     JSObject* object = asObject(base);
953     
954     for (unsigned i = structureSet.size(); i--;) {
955         Structure* structure = structureSet[i];
956         WatchpointSet* set = structure->propertyReplacementWatchpointSet(offset);
957         if (!set || !set->isStillValid())
958             return JSValue();
959         
960         ASSERT(structure->isValidOffset(offset));
961         ASSERT(!structure->isUncacheableDictionary());
962         
963         watchpoints().addLazily(set);
964     }
965     
966     // What follows may require some extra thought. We need this load to load a valid JSValue. If
967     // our profiling makes sense and we're still on track to generate code that won't be
968     // invalidated, then we have nothing to worry about. We do, however, have to worry about
969     // loading - and then using - an invalid JSValue in the case that unbeknownst to us our code
970     // is doomed.
971     //
972     // One argument in favor of this code is that it should definitely work because the butterfly
973     // is always set before the structure. However, we don't currently have a fence between those
974     // stores. It's not clear if this matters, however. We don't ever shrink the property storage.
975     // So, for this to fail, you'd need an access on a constant object pointer such that the inline
976     // caches told us that the object had a structure that it did not *yet* have, and then later,
977     // the object transitioned to that structure that the inline caches had alraedy seen. And then
978     // the processor reordered the stores. Seems unlikely and difficult to test. I believe that
979     // this is worth revisiting but it isn't worth losing sleep over. Filed:
980     // https://bugs.webkit.org/show_bug.cgi?id=134641
981     //
982     // For now, we just do the minimal thing: defend against the structure right now being
983     // incompatible with the getDirect we're trying to do. The easiest way to do that is to
984     // determine if the structure belongs to the proven set.
985     
986     if (!structureSet.contains(object->structure()))
987         return JSValue();
988     
989     return object->getDirect(offset);
990 }
991
992 JSValue Graph::tryGetConstantProperty(JSValue base, Structure* structure, PropertyOffset offset)
993 {
994     return tryGetConstantProperty(base, StructureSet(structure), offset);
995 }
996
997 JSValue Graph::tryGetConstantProperty(
998     JSValue base, const StructureAbstractValue& structure, PropertyOffset offset)
999 {
1000     if (structure.isTop() || structure.isClobbered())
1001         return JSValue();
1002     
1003     return tryGetConstantProperty(base, structure.set(), offset);
1004 }
1005
1006 JSValue Graph::tryGetConstantProperty(const AbstractValue& base, PropertyOffset offset)
1007 {
1008     return tryGetConstantProperty(base.m_value, base.m_structure, offset);
1009 }
1010
1011 JSLexicalEnvironment* Graph::tryGetActivation(Node* node)
1012 {
1013     return node->dynamicCastConstant<JSLexicalEnvironment*>();
1014 }
1015
1016 WriteBarrierBase<Unknown>* Graph::tryGetRegisters(Node* node)
1017 {
1018     JSLexicalEnvironment* lexicalEnvironment = tryGetActivation(node);
1019     if (!lexicalEnvironment)
1020         return 0;
1021     return lexicalEnvironment->registers();
1022 }
1023
1024 JSArrayBufferView* Graph::tryGetFoldableView(Node* node)
1025 {
1026     JSArrayBufferView* view = node->dynamicCastConstant<JSArrayBufferView*>();
1027     if (!view)
1028         return nullptr;
1029     if (!view->length())
1030         return nullptr;
1031     WTF::loadLoadFence();
1032     return view;
1033 }
1034
1035 JSArrayBufferView* Graph::tryGetFoldableView(Node* node, ArrayMode arrayMode)
1036 {
1037     if (arrayMode.typedArrayType() == NotTypedArray)
1038         return 0;
1039     return tryGetFoldableView(node);
1040 }
1041
1042 JSArrayBufferView* Graph::tryGetFoldableViewForChild1(Node* node)
1043 {
1044     return tryGetFoldableView(child(node, 0).node(), node->arrayMode());
1045 }
1046
1047 void Graph::registerFrozenValues()
1048 {
1049     m_codeBlock->constants().resize(0);
1050     for (FrozenValue* value : m_frozenValues) {
1051         if (value->structure())
1052             ASSERT(m_plan.weakReferences.contains(value->structure()));
1053         
1054         switch (value->strength()) {
1055         case FragileValue: {
1056             break;
1057         }
1058         case WeakValue: {
1059             m_plan.weakReferences.addLazily(value->value().asCell());
1060             break;
1061         }
1062         case StrongValue: {
1063             unsigned constantIndex = m_codeBlock->addConstantLazily();
1064             initializeLazyWriteBarrierForConstant(
1065                 m_plan.writeBarriers,
1066                 m_codeBlock->constants()[constantIndex],
1067                 m_codeBlock,
1068                 constantIndex,
1069                 m_codeBlock->ownerExecutable(),
1070                 value->value());
1071             break;
1072         } }
1073     }
1074     m_codeBlock->constants().shrinkToFit();
1075 }
1076
1077 void Graph::visitChildren(SlotVisitor& visitor)
1078 {
1079     for (FrozenValue* value : m_frozenValues) {
1080         visitor.appendUnbarrieredReadOnlyValue(value->value());
1081         visitor.appendUnbarrieredReadOnlyPointer(value->structure());
1082     }
1083     
1084     for (BlockIndex blockIndex = numBlocks(); blockIndex--;) {
1085         BasicBlock* block = this->block(blockIndex);
1086         if (!block)
1087             continue;
1088         
1089         for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
1090             Node* node = block->at(nodeIndex);
1091             
1092             switch (node->op()) {
1093             case CheckStructure:
1094                 for (unsigned i = node->structureSet().size(); i--;)
1095                     visitor.appendUnbarrieredReadOnlyPointer(node->structureSet()[i]);
1096                 break;
1097                 
1098             case NewObject:
1099             case ArrayifyToStructure:
1100             case NewStringObject:
1101                 visitor.appendUnbarrieredReadOnlyPointer(node->structure());
1102                 break;
1103                 
1104             case PutStructure:
1105             case AllocatePropertyStorage:
1106             case ReallocatePropertyStorage:
1107                 visitor.appendUnbarrieredReadOnlyPointer(
1108                     node->transition()->previous);
1109                 visitor.appendUnbarrieredReadOnlyPointer(
1110                     node->transition()->next);
1111                 break;
1112                 
1113             case MultiGetByOffset:
1114                 for (unsigned i = node->multiGetByOffsetData().variants.size(); i--;) {
1115                     GetByIdVariant& variant = node->multiGetByOffsetData().variants[i];
1116                     const StructureSet& set = variant.structureSet();
1117                     for (unsigned j = set.size(); j--;)
1118                         visitor.appendUnbarrieredReadOnlyPointer(set[j]);
1119
1120                     // Don't need to mark anything in the structure chain because that would
1121                     // have been decomposed into CheckStructure's. Don't need to mark the
1122                     // callLinkStatus because we wouldn't use MultiGetByOffset if any of the
1123                     // variants did that.
1124                     ASSERT(!variant.callLinkStatus());
1125                 }
1126                 break;
1127                     
1128             case MultiPutByOffset:
1129                 for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
1130                     PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
1131                     const StructureSet& set = variant.oldStructure();
1132                     for (unsigned j = set.size(); j--;)
1133                         visitor.appendUnbarrieredReadOnlyPointer(set[j]);
1134                     if (variant.kind() == PutByIdVariant::Transition)
1135                         visitor.appendUnbarrieredReadOnlyPointer(variant.newStructure());
1136                 }
1137                 break;
1138                 
1139             default:
1140                 break;
1141             }
1142         }
1143     }
1144 }
1145
1146 FrozenValue* Graph::freezeFragile(JSValue value)
1147 {
1148     if (UNLIKELY(!value))
1149         return FrozenValue::emptySingleton();
1150     
1151     auto result = m_frozenValueMap.add(JSValue::encode(value), nullptr);
1152     if (LIKELY(!result.isNewEntry))
1153         return result.iterator->value;
1154     
1155     return result.iterator->value = m_frozenValues.add(FrozenValue::freeze(value));
1156 }
1157
1158 FrozenValue* Graph::freeze(JSValue value)
1159 {
1160     FrozenValue* result = freezeFragile(value);
1161     result->strengthenTo(WeakValue);
1162     return result;
1163 }
1164
1165 FrozenValue* Graph::freezeStrong(JSValue value)
1166 {
1167     FrozenValue* result = freezeFragile(value);
1168     result->strengthenTo(StrongValue);
1169     return result;
1170 }
1171
1172 void Graph::convertToConstant(Node* node, FrozenValue* value)
1173 {
1174     if (value->structure())
1175         assertIsRegistered(value->structure());
1176     if (m_form == ThreadedCPS) {
1177         if (node->op() == GetLocal)
1178             dethread();
1179         else
1180             ASSERT(!node->hasVariableAccessData(*this));
1181     }
1182     node->convertToConstant(value);
1183 }
1184
1185 void Graph::convertToConstant(Node* node, JSValue value)
1186 {
1187     convertToConstant(node, freeze(value));
1188 }
1189
1190 void Graph::convertToStrongConstant(Node* node, JSValue value)
1191 {
1192     convertToConstant(node, freezeStrong(value));
1193 }
1194
1195 StructureRegistrationResult Graph::registerStructure(Structure* structure)
1196 {
1197     m_plan.weakReferences.addLazily(structure);
1198     if (m_plan.watchpoints.consider(structure))
1199         return StructureRegisteredAndWatched;
1200     return StructureRegisteredNormally;
1201 }
1202
1203 void Graph::assertIsRegistered(Structure* structure)
1204 {
1205     if (m_structureRegistrationState == HaveNotStartedRegistering)
1206         return;
1207     
1208     DFG_ASSERT(*this, nullptr, m_plan.weakReferences.contains(structure));
1209     
1210     if (!structure->dfgShouldWatch())
1211         return;
1212     if (watchpoints().isWatched(structure->transitionWatchpointSet()))
1213         return;
1214     
1215     DFG_CRASH(*this, nullptr, toCString("Structure ", pointerDump(structure), " is watchable but isn't being watched.").data());
1216 }
1217
1218 NO_RETURN_DUE_TO_CRASH static void crash(
1219     Graph& graph, const CString& whileText, const char* file, int line, const char* function,
1220     const char* assertion)
1221 {
1222     startCrashing();
1223     dataLog("DFG ASSERTION FAILED: ", assertion, "\n");
1224     dataLog(file, "(", line, ") : ", function, "\n");
1225     dataLog("\n");
1226     dataLog(whileText);
1227     dataLog("Graph at time of failure:\n");
1228     graph.dump();
1229     dataLog("\n");
1230     dataLog("DFG ASSERTION FAILED: ", assertion, "\n");
1231     dataLog(file, "(", line, ") : ", function, "\n");
1232     CRASH_WITH_SECURITY_IMPLICATION();
1233 }
1234
1235 void Graph::handleAssertionFailure(
1236     std::nullptr_t, const char* file, int line, const char* function, const char* assertion)
1237 {
1238     crash(*this, "", file, line, function, assertion);
1239 }
1240
1241 void Graph::handleAssertionFailure(
1242     Node* node, const char* file, int line, const char* function, const char* assertion)
1243 {
1244     crash(*this, toCString("While handling node ", node, "\n\n"), file, line, function, assertion);
1245 }
1246
1247 void Graph::handleAssertionFailure(
1248     BasicBlock* block, const char* file, int line, const char* function, const char* assertion)
1249 {
1250     crash(*this, toCString("While handling block ", pointerDump(block), "\n\n"), file, line, function, assertion);
1251 }
1252
1253 } } // namespace JSC::DFG
1254
1255 #endif // ENABLE(DFG_JIT)