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