acbe0d890bdde584a6eaae2e4c30422444e8af98
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGGraph.h
1 /*
2  * Copyright (C) 2011, 2012, 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 #ifndef DFGGraph_h
27 #define DFGGraph_h
28
29 #if ENABLE(DFG_JIT)
30
31 #include "AssemblyHelpers.h"
32 #include "CodeBlock.h"
33 #include "DFGArgumentPosition.h"
34 #include "DFGBasicBlock.h"
35 #include "DFGDominators.h"
36 #include "DFGFrozenValue.h"
37 #include "DFGLongLivedState.h"
38 #include "DFGNaturalLoops.h"
39 #include "DFGNode.h"
40 #include "DFGNodeAllocator.h"
41 #include "DFGPlan.h"
42 #include "DFGScannable.h"
43 #include "JSStack.h"
44 #include "MethodOfGettingAValueProfile.h"
45 #include <unordered_map>
46 #include <wtf/BitVector.h>
47 #include <wtf/HashMap.h>
48 #include <wtf/Vector.h>
49 #include <wtf/StdLibExtras.h>
50
51 namespace JSC {
52
53 class CodeBlock;
54 class ExecState;
55
56 namespace DFG {
57
58 struct StorageAccessData {
59     PropertyOffset offset;
60     unsigned identifierNumber;
61 };
62
63 struct InlineVariableData {
64     InlineCallFrame* inlineCallFrame;
65     unsigned argumentPositionStart;
66     VariableAccessData* calleeVariable;
67 };
68
69 enum AddSpeculationMode {
70     DontSpeculateInt32,
71     SpeculateInt32AndTruncateConstants,
72     SpeculateInt32
73 };
74
75 //
76 // === Graph ===
77 //
78 // The order may be significant for nodes with side-effects (property accesses, value conversions).
79 // Nodes that are 'dead' remain in the vector with refCount 0.
80 class Graph : public virtual Scannable {
81 public:
82     Graph(VM&, Plan&, LongLivedState&);
83     ~Graph();
84     
85     void changeChild(Edge& edge, Node* newNode)
86     {
87         edge.setNode(newNode);
88     }
89     
90     void changeEdge(Edge& edge, Edge newEdge)
91     {
92         edge = newEdge;
93     }
94     
95     void compareAndSwap(Edge& edge, Node* oldNode, Node* newNode)
96     {
97         if (edge.node() != oldNode)
98             return;
99         changeChild(edge, newNode);
100     }
101     
102     void compareAndSwap(Edge& edge, Edge oldEdge, Edge newEdge)
103     {
104         if (edge != oldEdge)
105             return;
106         changeEdge(edge, newEdge);
107     }
108     
109     void performSubstitution(Node* node)
110     {
111         if (node->flags() & NodeHasVarArgs) {
112             for (unsigned childIdx = node->firstChild(); childIdx < node->firstChild() + node->numChildren(); childIdx++)
113                 performSubstitutionForEdge(m_varArgChildren[childIdx]);
114         } else {
115             performSubstitutionForEdge(node->child1());
116             performSubstitutionForEdge(node->child2());
117             performSubstitutionForEdge(node->child3());
118         }
119     }
120     
121     void performSubstitutionForEdge(Edge& child)
122     {
123         // Check if this operand is actually unused.
124         if (!child)
125             return;
126         
127         // Check if there is any replacement.
128         Node* replacement = child->replacement;
129         if (!replacement)
130             return;
131         
132         child.setNode(replacement);
133         
134         // There is definitely a replacement. Assert that the replacement does not
135         // have a replacement.
136         ASSERT(!child->replacement);
137     }
138     
139     template<typename... Params>
140     Node* addNode(SpeculatedType type, Params... params)
141     {
142         Node* node = new (m_allocator) Node(params...);
143         node->predict(type);
144         return node;
145     }
146
147     void dethread();
148     
149     FrozenValue* freezeFragile(JSValue value);
150     FrozenValue* freeze(JSValue value); // We use weak freezing by default. Shorthand for freezeFragile(value)->strengthenTo(WeakValue);
151     FrozenValue* freezeStrong(JSValue value); // Shorthand for freezeFragile(value)->strengthenTo(StrongValue).
152     
153     void convertToConstant(Node* node, FrozenValue* value);
154     void convertToConstant(Node* node, JSValue value);
155     void convertToStrongConstant(Node* node, JSValue value);
156     
157     StructureRegistrationResult registerStructure(Structure* structure);
158     void assertIsRegistered(Structure* structure);
159     
160     // CodeBlock is optional, but may allow additional information to be dumped (e.g. Identifier names).
161     void dump(PrintStream& = WTF::dataFile(), DumpContext* = 0);
162     enum PhiNodeDumpMode { DumpLivePhisOnly, DumpAllPhis };
163     void dumpBlockHeader(PrintStream&, const char* prefix, BasicBlock*, PhiNodeDumpMode, DumpContext*);
164     void dump(PrintStream&, Edge);
165     void dump(PrintStream&, const char* prefix, Node*, DumpContext* = 0);
166     static int amountOfNodeWhiteSpace(Node*);
167     static void printNodeWhiteSpace(PrintStream&, Node*);
168
169     // Dump the code origin of the given node as a diff from the code origin of the
170     // preceding node. Returns true if anything was printed.
171     bool dumpCodeOrigin(PrintStream&, const char* prefix, Node* previousNode, Node* currentNode, DumpContext*);
172
173     AddSpeculationMode addSpeculationMode(Node* add, bool leftShouldSpeculateInt32, bool rightShouldSpeculateInt32, PredictionPass pass)
174     {
175         ASSERT(add->op() == ValueAdd || add->op() == ArithAdd || add->op() == ArithSub);
176         
177         RareCaseProfilingSource source = add->sourceFor(pass);
178         
179         Node* left = add->child1().node();
180         Node* right = add->child2().node();
181         
182         if (left->hasConstant())
183             return addImmediateShouldSpeculateInt32(add, rightShouldSpeculateInt32, left, source);
184         if (right->hasConstant())
185             return addImmediateShouldSpeculateInt32(add, leftShouldSpeculateInt32, right, source);
186         
187         return (leftShouldSpeculateInt32 && rightShouldSpeculateInt32 && add->canSpeculateInt32(source)) ? SpeculateInt32 : DontSpeculateInt32;
188     }
189     
190     AddSpeculationMode valueAddSpeculationMode(Node* add, PredictionPass pass)
191     {
192         return addSpeculationMode(
193             add,
194             add->child1()->shouldSpeculateInt32OrBooleanExpectingDefined(),
195             add->child2()->shouldSpeculateInt32OrBooleanExpectingDefined(),
196             pass);
197     }
198     
199     AddSpeculationMode arithAddSpeculationMode(Node* add, PredictionPass pass)
200     {
201         return addSpeculationMode(
202             add,
203             add->child1()->shouldSpeculateInt32OrBooleanForArithmetic(),
204             add->child2()->shouldSpeculateInt32OrBooleanForArithmetic(),
205             pass);
206     }
207     
208     AddSpeculationMode addSpeculationMode(Node* add, PredictionPass pass)
209     {
210         if (add->op() == ValueAdd)
211             return valueAddSpeculationMode(add, pass);
212         
213         return arithAddSpeculationMode(add, pass);
214     }
215     
216     bool addShouldSpeculateInt32(Node* add, PredictionPass pass)
217     {
218         return addSpeculationMode(add, pass) != DontSpeculateInt32;
219     }
220     
221     bool addShouldSpeculateMachineInt(Node* add)
222     {
223         if (!enableInt52())
224             return false;
225         
226         Node* left = add->child1().node();
227         Node* right = add->child2().node();
228
229         bool speculation;
230         if (add->op() == ValueAdd)
231             speculation = Node::shouldSpeculateMachineInt(left, right);
232         else
233             speculation = Node::shouldSpeculateMachineInt(left, right);
234
235         return speculation && !hasExitSite(add, Int52Overflow);
236     }
237     
238     bool mulShouldSpeculateInt32(Node* mul, PredictionPass pass)
239     {
240         ASSERT(mul->op() == ArithMul);
241         
242         Node* left = mul->child1().node();
243         Node* right = mul->child2().node();
244         
245         return Node::shouldSpeculateInt32OrBooleanForArithmetic(left, right)
246             && mul->canSpeculateInt32(mul->sourceFor(pass));
247     }
248     
249     bool mulShouldSpeculateMachineInt(Node* mul, PredictionPass pass)
250     {
251         ASSERT(mul->op() == ArithMul);
252         
253         if (!enableInt52())
254             return false;
255         
256         Node* left = mul->child1().node();
257         Node* right = mul->child2().node();
258
259         return Node::shouldSpeculateMachineInt(left, right)
260             && mul->canSpeculateInt52(pass)
261             && !hasExitSite(mul, Int52Overflow);
262     }
263     
264     bool negateShouldSpeculateInt32(Node* negate, PredictionPass pass)
265     {
266         ASSERT(negate->op() == ArithNegate);
267         return negate->child1()->shouldSpeculateInt32OrBooleanForArithmetic()
268             && negate->canSpeculateInt32(pass);
269     }
270     
271     bool negateShouldSpeculateMachineInt(Node* negate, PredictionPass pass)
272     {
273         ASSERT(negate->op() == ArithNegate);
274         if (!enableInt52())
275             return false;
276         return negate->child1()->shouldSpeculateMachineInt()
277             && !hasExitSite(negate, Int52Overflow)
278             && negate->canSpeculateInt52(pass);
279     }
280     
281     VirtualRegister bytecodeRegisterForArgument(CodeOrigin codeOrigin, int argument)
282     {
283         return VirtualRegister(
284             codeOrigin.inlineCallFrame->stackOffset +
285             baselineCodeBlockFor(codeOrigin)->argumentIndexAfterCapture(argument));
286     }
287     
288     static const char *opName(NodeType);
289     
290     StructureSet* addStructureSet(const StructureSet& structureSet)
291     {
292         ASSERT(structureSet.size());
293         m_structureSet.append(structureSet);
294         return &m_structureSet.last();
295     }
296     
297     JSGlobalObject* globalObjectFor(CodeOrigin codeOrigin)
298     {
299         return m_codeBlock->globalObjectFor(codeOrigin);
300     }
301     
302     JSObject* globalThisObjectFor(CodeOrigin codeOrigin)
303     {
304         JSGlobalObject* object = globalObjectFor(codeOrigin);
305         return jsCast<JSObject*>(object->methodTable()->toThis(object, object->globalExec(), NotStrictMode));
306     }
307     
308     ScriptExecutable* executableFor(InlineCallFrame* inlineCallFrame)
309     {
310         if (!inlineCallFrame)
311             return m_codeBlock->ownerExecutable();
312         
313         return inlineCallFrame->executable.get();
314     }
315     
316     ScriptExecutable* executableFor(const CodeOrigin& codeOrigin)
317     {
318         return executableFor(codeOrigin.inlineCallFrame);
319     }
320     
321     CodeBlock* baselineCodeBlockFor(InlineCallFrame* inlineCallFrame)
322     {
323         if (!inlineCallFrame)
324             return m_profiledBlock;
325         return baselineCodeBlockForInlineCallFrame(inlineCallFrame);
326     }
327     
328     CodeBlock* baselineCodeBlockFor(const CodeOrigin& codeOrigin)
329     {
330         return baselineCodeBlockForOriginAndBaselineCodeBlock(codeOrigin, m_profiledBlock);
331     }
332     
333     bool isStrictModeFor(CodeOrigin codeOrigin)
334     {
335         if (!codeOrigin.inlineCallFrame)
336             return m_codeBlock->isStrictMode();
337         return jsCast<FunctionExecutable*>(codeOrigin.inlineCallFrame->executable.get())->isStrictMode();
338     }
339     
340     ECMAMode ecmaModeFor(CodeOrigin codeOrigin)
341     {
342         return isStrictModeFor(codeOrigin) ? StrictMode : NotStrictMode;
343     }
344     
345     bool masqueradesAsUndefinedWatchpointIsStillValid(const CodeOrigin& codeOrigin)
346     {
347         return globalObjectFor(codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid();
348     }
349     
350     bool hasGlobalExitSite(const CodeOrigin& codeOrigin, ExitKind exitKind)
351     {
352         return baselineCodeBlockFor(codeOrigin)->hasExitSite(FrequentExitSite(exitKind));
353     }
354     
355     bool hasExitSite(const CodeOrigin& codeOrigin, ExitKind exitKind)
356     {
357         return baselineCodeBlockFor(codeOrigin)->hasExitSite(FrequentExitSite(codeOrigin.bytecodeIndex, exitKind));
358     }
359     
360     bool hasExitSite(Node* node, ExitKind exitKind)
361     {
362         return hasExitSite(node->origin.semantic, exitKind);
363     }
364     
365     VirtualRegister argumentsRegisterFor(InlineCallFrame* inlineCallFrame)
366     {
367         if (!inlineCallFrame)
368             return m_profiledBlock->argumentsRegister();
369         
370         return VirtualRegister(baselineCodeBlockForInlineCallFrame(
371             inlineCallFrame)->argumentsRegister().offset() +
372             inlineCallFrame->stackOffset);
373     }
374     
375     VirtualRegister argumentsRegisterFor(const CodeOrigin& codeOrigin)
376     {
377         return argumentsRegisterFor(codeOrigin.inlineCallFrame);
378     }
379     
380     VirtualRegister machineArgumentsRegisterFor(InlineCallFrame* inlineCallFrame)
381     {
382         if (!inlineCallFrame)
383             return m_codeBlock->argumentsRegister();
384         
385         return inlineCallFrame->argumentsRegister;
386     }
387     
388     VirtualRegister machineArgumentsRegisterFor(const CodeOrigin& codeOrigin)
389     {
390         return machineArgumentsRegisterFor(codeOrigin.inlineCallFrame);
391     }
392     
393     VirtualRegister uncheckedArgumentsRegisterFor(InlineCallFrame* inlineCallFrame)
394     {
395         if (!inlineCallFrame)
396             return m_profiledBlock->uncheckedArgumentsRegister();
397         
398         CodeBlock* codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame);
399         if (!codeBlock->usesArguments())
400             return VirtualRegister();
401         
402         return VirtualRegister(codeBlock->argumentsRegister().offset() +
403             inlineCallFrame->stackOffset);
404     }
405     
406     VirtualRegister uncheckedArgumentsRegisterFor(const CodeOrigin& codeOrigin)
407     {
408         return uncheckedArgumentsRegisterFor(codeOrigin.inlineCallFrame);
409     }
410     
411     VirtualRegister activationRegister()
412     {
413         return m_profiledBlock->activationRegister();
414     }
415     
416     VirtualRegister uncheckedActivationRegister()
417     {
418         return m_profiledBlock->uncheckedActivationRegister();
419     }
420     
421     VirtualRegister machineActivationRegister()
422     {
423         return m_profiledBlock->activationRegister();
424     }
425     
426     VirtualRegister uncheckedMachineActivationRegister()
427     {
428         return m_profiledBlock->uncheckedActivationRegister();
429     }
430     
431     ValueProfile* valueProfileFor(Node* node)
432     {
433         if (!node)
434             return 0;
435         
436         CodeBlock* profiledBlock = baselineCodeBlockFor(node->origin.semantic);
437         
438         if (node->op() == GetArgument)
439             return profiledBlock->valueProfileForArgument(node->local().toArgument());
440         
441         if (node->hasLocal(*this)) {
442             if (m_form == SSA)
443                 return 0;
444             if (!node->local().isArgument())
445                 return 0;
446             int argument = node->local().toArgument();
447             if (node->variableAccessData() != m_arguments[argument]->variableAccessData())
448                 return 0;
449             return profiledBlock->valueProfileForArgument(argument);
450         }
451         
452         if (node->hasHeapPrediction())
453             return profiledBlock->valueProfileForBytecodeOffset(node->origin.semantic.bytecodeIndex);
454         
455         return 0;
456     }
457     
458     MethodOfGettingAValueProfile methodOfGettingAValueProfileFor(Node* node)
459     {
460         if (!node)
461             return MethodOfGettingAValueProfile();
462         
463         CodeBlock* profiledBlock = baselineCodeBlockFor(node->origin.semantic);
464         
465         if (node->op() == GetLocal) {
466             return MethodOfGettingAValueProfile::fromLazyOperand(
467                 profiledBlock,
468                 LazyOperandValueProfileKey(
469                     node->origin.semantic.bytecodeIndex, node->local()));
470         }
471         
472         return MethodOfGettingAValueProfile(valueProfileFor(node));
473     }
474     
475     bool usesArguments() const
476     {
477         return m_codeBlock->usesArguments();
478     }
479     
480     BlockIndex numBlocks() const { return m_blocks.size(); }
481     BasicBlock* block(BlockIndex blockIndex) const { return m_blocks[blockIndex].get(); }
482     BasicBlock* lastBlock() const { return block(numBlocks() - 1); }
483
484     void appendBlock(PassRefPtr<BasicBlock> basicBlock)
485     {
486         basicBlock->index = m_blocks.size();
487         m_blocks.append(basicBlock);
488     }
489     
490     void killBlock(BlockIndex blockIndex)
491     {
492         m_blocks[blockIndex].clear();
493     }
494     
495     void killBlock(BasicBlock* basicBlock)
496     {
497         killBlock(basicBlock->index);
498     }
499     
500     void killBlockAndItsContents(BasicBlock*);
501     
502     void killUnreachableBlocks();
503     
504     bool isPredictedNumerical(Node* node)
505     {
506         return isNumerical(node->child1().useKind()) && isNumerical(node->child2().useKind());
507     }
508     
509     // Note that a 'true' return does not actually mean that the ByVal access clobbers nothing.
510     // It really means that it will not clobber the entire world. It's still up to you to
511     // carefully consider things like:
512     // - PutByVal definitely changes the array it stores to, and may even change its length.
513     // - PutByOffset definitely changes the object it stores to.
514     // - and so on.
515     bool byValIsPure(Node* node)
516     {
517         switch (node->arrayMode().type()) {
518         case Array::Generic:
519             return false;
520         case Array::Int32:
521         case Array::Double:
522         case Array::Contiguous:
523         case Array::ArrayStorage:
524             return !node->arrayMode().isOutOfBounds();
525         case Array::SlowPutArrayStorage:
526             return !node->arrayMode().mayStoreToHole();
527         case Array::String:
528             return node->op() == GetByVal && node->arrayMode().isInBounds();
529 #if USE(JSVALUE32_64)
530         case Array::Arguments:
531             if (node->op() == GetByVal)
532                 return true;
533             return false;
534 #endif // USE(JSVALUE32_64)
535         default:
536             return true;
537         }
538     }
539     
540     bool clobbersWorld(Node* node)
541     {
542         if (node->flags() & NodeClobbersWorld)
543             return true;
544         if (!(node->flags() & NodeMightClobber))
545             return false;
546         switch (node->op()) {
547         case GetByVal:
548         case PutByValDirect:
549         case PutByVal:
550         case PutByValAlias:
551             return !byValIsPure(node);
552         case ToString:
553             switch (node->child1().useKind()) {
554             case StringObjectUse:
555             case StringOrStringObjectUse:
556                 return false;
557             case CellUse:
558             case UntypedUse:
559                 return true;
560             default:
561                 RELEASE_ASSERT_NOT_REACHED();
562                 return true;
563             }
564         default:
565             RELEASE_ASSERT_NOT_REACHED();
566             return true; // If by some oddity we hit this case in release build it's safer to have CSE assume the worst.
567         }
568     }
569     
570     void determineReachability();
571     void resetReachability();
572     
573     unsigned varArgNumChildren(Node* node)
574     {
575         ASSERT(node->flags() & NodeHasVarArgs);
576         return node->numChildren();
577     }
578     
579     unsigned numChildren(Node* node)
580     {
581         if (node->flags() & NodeHasVarArgs)
582             return varArgNumChildren(node);
583         return AdjacencyList::Size;
584     }
585     
586     Edge& varArgChild(Node* node, unsigned index)
587     {
588         ASSERT(node->flags() & NodeHasVarArgs);
589         return m_varArgChildren[node->firstChild() + index];
590     }
591     
592     Edge& child(Node* node, unsigned index)
593     {
594         if (node->flags() & NodeHasVarArgs)
595             return varArgChild(node, index);
596         return node->children.child(index);
597     }
598     
599     void voteNode(Node* node, unsigned ballot, float weight = 1)
600     {
601         switch (node->op()) {
602         case ValueToInt32:
603         case UInt32ToNumber:
604             node = node->child1().node();
605             break;
606         default:
607             break;
608         }
609         
610         if (node->op() == GetLocal)
611             node->variableAccessData()->vote(ballot, weight);
612     }
613     
614     void voteNode(Edge edge, unsigned ballot, float weight = 1)
615     {
616         voteNode(edge.node(), ballot, weight);
617     }
618     
619     void voteChildren(Node* node, unsigned ballot, float weight = 1)
620     {
621         if (node->flags() & NodeHasVarArgs) {
622             for (unsigned childIdx = node->firstChild();
623                 childIdx < node->firstChild() + node->numChildren();
624                 childIdx++) {
625                 if (!!m_varArgChildren[childIdx])
626                     voteNode(m_varArgChildren[childIdx], ballot, weight);
627             }
628             return;
629         }
630         
631         if (!node->child1())
632             return;
633         voteNode(node->child1(), ballot, weight);
634         if (!node->child2())
635             return;
636         voteNode(node->child2(), ballot, weight);
637         if (!node->child3())
638             return;
639         voteNode(node->child3(), ballot, weight);
640     }
641     
642     template<typename T> // T = Node* or Edge
643     void substitute(BasicBlock& block, unsigned startIndexInBlock, T oldThing, T newThing)
644     {
645         for (unsigned indexInBlock = startIndexInBlock; indexInBlock < block.size(); ++indexInBlock) {
646             Node* node = block[indexInBlock];
647             if (node->flags() & NodeHasVarArgs) {
648                 for (unsigned childIdx = node->firstChild(); childIdx < node->firstChild() + node->numChildren(); ++childIdx) {
649                     if (!!m_varArgChildren[childIdx])
650                         compareAndSwap(m_varArgChildren[childIdx], oldThing, newThing);
651                 }
652                 continue;
653             }
654             if (!node->child1())
655                 continue;
656             compareAndSwap(node->children.child1(), oldThing, newThing);
657             if (!node->child2())
658                 continue;
659             compareAndSwap(node->children.child2(), oldThing, newThing);
660             if (!node->child3())
661                 continue;
662             compareAndSwap(node->children.child3(), oldThing, newThing);
663         }
664     }
665     
666     // Use this if you introduce a new GetLocal and you know that you introduced it *before*
667     // any GetLocals in the basic block.
668     // FIXME: it may be appropriate, in the future, to generalize this to handle GetLocals
669     // introduced anywhere in the basic block.
670     void substituteGetLocal(BasicBlock& block, unsigned startIndexInBlock, VariableAccessData* variableAccessData, Node* newGetLocal);
671     
672     void invalidateCFG();
673     
674     void clearFlagsOnAllNodes(NodeFlags);
675     
676     void clearReplacements();
677     void initializeNodeOwners();
678     
679     BlockList blocksInPreOrder();
680     BlockList blocksInPostOrder();
681     
682     Profiler::Compilation* compilation() { return m_plan.compilation.get(); }
683     
684     DesiredIdentifiers& identifiers() { return m_plan.identifiers; }
685     DesiredWatchpoints& watchpoints() { return m_plan.watchpoints; }
686     
687     FullBytecodeLiveness& livenessFor(CodeBlock*);
688     FullBytecodeLiveness& livenessFor(InlineCallFrame*);
689     bool isLiveInBytecode(VirtualRegister, CodeOrigin);
690     
691     unsigned frameRegisterCount();
692     unsigned stackPointerOffset();
693     unsigned requiredRegisterCountForExit();
694     unsigned requiredRegisterCountForExecutionAndExit();
695     
696     JSValue tryGetConstantProperty(JSValue base, const StructureSet&, PropertyOffset);
697     JSValue tryGetConstantProperty(JSValue base, Structure*, PropertyOffset);
698     JSValue tryGetConstantProperty(JSValue base, const StructureAbstractValue&, PropertyOffset);
699     JSValue tryGetConstantProperty(const AbstractValue&, PropertyOffset);
700     
701     JSActivation* tryGetActivation(Node*);
702     WriteBarrierBase<Unknown>* tryGetRegisters(Node*);
703     
704     JSArrayBufferView* tryGetFoldableView(Node*);
705     JSArrayBufferView* tryGetFoldableView(Node*, ArrayMode);
706     JSArrayBufferView* tryGetFoldableViewForChild1(Node*);
707     
708     void registerFrozenValues();
709     
710     virtual void visitChildren(SlotVisitor&) override;
711     
712     NO_RETURN_DUE_TO_CRASH void handleAssertionFailure(
713         Node* node, const char* file, int line, const char* function,
714         const char* assertion);
715     
716     VM& m_vm;
717     Plan& m_plan;
718     CodeBlock* m_codeBlock;
719     CodeBlock* m_profiledBlock;
720     
721     NodeAllocator& m_allocator;
722
723     Operands<FrozenValue*> m_mustHandleValues;
724     
725     Vector< RefPtr<BasicBlock> , 8> m_blocks;
726     Vector<Edge, 16> m_varArgChildren;
727
728     HashMap<EncodedJSValue, FrozenValue*, EncodedJSValueHash, EncodedJSValueHashTraits> m_frozenValueMap;
729     Bag<FrozenValue> m_frozenValues;
730     
731     Vector<StorageAccessData> m_storageAccessData;
732     Vector<Node*, 8> m_arguments;
733     SegmentedVector<VariableAccessData, 16> m_variableAccessData;
734     SegmentedVector<ArgumentPosition, 8> m_argumentPositions;
735     SegmentedVector<StructureSet, 16> m_structureSet;
736     Bag<Transition> m_transitions;
737     SegmentedVector<NewArrayBufferData, 4> m_newArrayBufferData;
738     Bag<BranchData> m_branchData;
739     Bag<SwitchData> m_switchData;
740     Bag<MultiGetByOffsetData> m_multiGetByOffsetData;
741     Bag<MultiPutByOffsetData> m_multiPutByOffsetData;
742     Vector<InlineVariableData, 4> m_inlineVariableData;
743     HashMap<CodeBlock*, std::unique_ptr<FullBytecodeLiveness>> m_bytecodeLiveness;
744     bool m_hasArguments;
745     HashSet<ExecutableBase*> m_executablesWhoseArgumentsEscaped;
746     BitVector m_lazyVars;
747     Dominators m_dominators;
748     NaturalLoops m_naturalLoops;
749     unsigned m_localVars;
750     unsigned m_nextMachineLocal;
751     unsigned m_parameterSlots;
752     int m_machineCaptureStart;
753     std::unique_ptr<SlowArgument[]> m_slowArguments;
754
755 #if USE(JSVALUE32_64)
756     std::unordered_map<int64_t, double*> m_doubleConstantsMap;
757     std::unique_ptr<Bag<double>> m_doubleConstants;
758 #endif
759     
760     OptimizationFixpointState m_fixpointState;
761     StructureRegistrationState m_structureRegistrationState;
762     GraphForm m_form;
763     UnificationState m_unificationState;
764     RefCountState m_refCountState;
765 private:
766     
767     void handleSuccessor(Vector<BasicBlock*, 16>& worklist, BasicBlock*, BasicBlock* successor);
768     
769     AddSpeculationMode addImmediateShouldSpeculateInt32(Node* add, bool variableShouldSpeculateInt32, Node* immediate, RareCaseProfilingSource source)
770     {
771         ASSERT(immediate->hasConstant());
772         
773         JSValue immediateValue = immediate->asJSValue();
774         if (!immediateValue.isNumber() && !immediateValue.isBoolean())
775             return DontSpeculateInt32;
776         
777         if (!variableShouldSpeculateInt32)
778             return DontSpeculateInt32;
779         
780         if (immediateValue.isInt32() || immediateValue.isBoolean())
781             return add->canSpeculateInt32(source) ? SpeculateInt32 : DontSpeculateInt32;
782         
783         double doubleImmediate = immediateValue.asDouble();
784         const double twoToThe48 = 281474976710656.0;
785         if (doubleImmediate < -twoToThe48 || doubleImmediate > twoToThe48)
786             return DontSpeculateInt32;
787         
788         return bytecodeCanTruncateInteger(add->arithNodeFlags()) ? SpeculateInt32AndTruncateConstants : DontSpeculateInt32;
789     }
790 };
791
792 #define DFG_NODE_DO_TO_CHILDREN(graph, node, thingToDo) do {            \
793         Node* _node = (node);                                           \
794         if (_node->flags() & NodeHasVarArgs) {                          \
795             for (unsigned _childIdx = _node->firstChild();              \
796                 _childIdx < _node->firstChild() + _node->numChildren(); \
797                 _childIdx++) {                                          \
798                 if (!!(graph).m_varArgChildren[_childIdx])              \
799                     thingToDo(_node, (graph).m_varArgChildren[_childIdx]); \
800             }                                                           \
801         } else {                                                        \
802             if (!_node->child1()) {                                     \
803                 ASSERT(                                                 \
804                     !_node->child2()                                    \
805                     && !_node->child3());                               \
806                 break;                                                  \
807             }                                                           \
808             thingToDo(_node, _node->child1());                          \
809                                                                         \
810             if (!_node->child2()) {                                     \
811                 ASSERT(!_node->child3());                               \
812                 break;                                                  \
813             }                                                           \
814             thingToDo(_node, _node->child2());                          \
815                                                                         \
816             if (!_node->child3())                                       \
817                 break;                                                  \
818             thingToDo(_node, _node->child3());                          \
819         }                                                               \
820     } while (false)
821
822 #define DFG_ASSERT(graph, node, assertion) do {                         \
823         if (!!(assertion))                                              \
824             break;                                                      \
825         (graph).handleAssertionFailure(                                 \
826             (node), __FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion); \
827     } while (false)
828
829 #define DFG_CRASH(graph, node, reason)                                  \
830     (graph).handleAssertionFailure(                                     \
831         (node), __FILE__, __LINE__, WTF_PRETTY_FUNCTION, (reason));
832
833 } } // namespace JSC::DFG
834
835 #endif
836 #endif