The DFG should be able to tier-up and OSR enter into the FTL
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGGraph.h
1 /*
2  * Copyright (C) 2011, 2012, 2013 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 #include <wtf/Platform.h>
30
31 #if ENABLE(DFG_JIT)
32
33 #include "CodeBlock.h"
34 #include "DFGArgumentPosition.h"
35 #include "DFGAssemblyHelpers.h"
36 #include "DFGBasicBlock.h"
37 #include "DFGDominators.h"
38 #include "DFGLongLivedState.h"
39 #include "DFGNaturalLoops.h"
40 #include "DFGNode.h"
41 #include "DFGNodeAllocator.h"
42 #include "DFGPlan.h"
43 #include "DFGVariadicFunction.h"
44 #include "JSStack.h"
45 #include "MethodOfGettingAValueProfile.h"
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 enum AddSpeculationMode {
64     DontSpeculateInteger,
65     SpeculateIntegerAndTruncateConstants,
66     SpeculateInteger
67 };
68
69 //
70 // === Graph ===
71 //
72 // The order may be significant for nodes with side-effects (property accesses, value conversions).
73 // Nodes that are 'dead' remain in the vector with refCount 0.
74 class Graph {
75 public:
76     Graph(VM&, Plan&, LongLivedState&);
77     ~Graph();
78     
79     void changeChild(Edge& edge, Node* newNode)
80     {
81         edge.setNode(newNode);
82     }
83     
84     void changeEdge(Edge& edge, Edge newEdge)
85     {
86         edge = newEdge;
87     }
88     
89     void compareAndSwap(Edge& edge, Node* oldNode, Node* newNode)
90     {
91         if (edge.node() != oldNode)
92             return;
93         changeChild(edge, newNode);
94     }
95     
96     void compareAndSwap(Edge& edge, Edge oldEdge, Edge newEdge)
97     {
98         if (edge != oldEdge)
99             return;
100         changeEdge(edge, newEdge);
101     }
102     
103     void performSubstitution(Node* node)
104     {
105         if (node->flags() & NodeHasVarArgs) {
106             for (unsigned childIdx = node->firstChild(); childIdx < node->firstChild() + node->numChildren(); childIdx++)
107                 performSubstitutionForEdge(m_varArgChildren[childIdx]);
108         } else {
109             performSubstitutionForEdge(node->child1());
110             performSubstitutionForEdge(node->child2());
111             performSubstitutionForEdge(node->child3());
112         }
113     }
114     
115     void performSubstitutionForEdge(Edge& child)
116     {
117         // Check if this operand is actually unused.
118         if (!child)
119             return;
120         
121         // Check if there is any replacement.
122         Node* replacement = child->misc.replacement;
123         if (!replacement)
124             return;
125         
126         child.setNode(replacement);
127         
128         // There is definitely a replacement. Assert that the replacement does not
129         // have a replacement.
130         ASSERT(!child->misc.replacement);
131     }
132     
133 #define DFG_DEFINE_ADD_NODE(templatePre, templatePost, typeParams, valueParamsComma, valueParams, valueArgs) \
134     templatePre typeParams templatePost Node* addNode(SpeculatedType type valueParamsComma valueParams) \
135     { \
136         Node* node = new (m_allocator) Node(valueArgs); \
137         node->predict(type); \
138         return node; \
139     }
140     DFG_VARIADIC_TEMPLATE_FUNCTION(DFG_DEFINE_ADD_NODE)
141 #undef DFG_DEFINE_ADD_NODE
142
143     void dethread();
144     
145     void convertToConstant(Node* node, unsigned constantNumber)
146     {
147         if (node->op() == GetLocal)
148             dethread();
149         else
150             ASSERT(!node->hasVariableAccessData(*this));
151         node->convertToConstant(constantNumber);
152     }
153     
154     unsigned constantRegisterForConstant(JSValue value)
155     {
156         unsigned constantRegister;
157         if (!m_codeBlock->findConstant(value, constantRegister)) {
158             constantRegister = m_codeBlock->addConstantLazily();
159             initializeLazyWriteBarrierForConstant(
160                 m_plan.writeBarriers,
161                 m_codeBlock->constants()[constantRegister],
162                 m_codeBlock,
163                 constantRegister,
164                 m_codeBlock->ownerExecutable(),
165                 value);
166         }
167         return constantRegister;
168     }
169     
170     void convertToConstant(Node* node, JSValue value)
171     {
172         convertToConstant(node, constantRegisterForConstant(value));
173     }
174
175     // CodeBlock is optional, but may allow additional information to be dumped (e.g. Identifier names).
176     void dump(PrintStream& = WTF::dataFile(), DumpContext* = 0);
177     enum PhiNodeDumpMode { DumpLivePhisOnly, DumpAllPhis };
178     void dumpBlockHeader(PrintStream&, const char* prefix, BasicBlock*, PhiNodeDumpMode, DumpContext* context);
179     void dump(PrintStream&, Edge);
180     void dump(PrintStream&, const char* prefix, Node*, DumpContext* = 0);
181     static int amountOfNodeWhiteSpace(Node*);
182     static void printNodeWhiteSpace(PrintStream&, Node*);
183
184     // Dump the code origin of the given node as a diff from the code origin of the
185     // preceding node. Returns true if anything was printed.
186     bool dumpCodeOrigin(PrintStream&, const char* prefix, Node* previousNode, Node* currentNode, DumpContext* context);
187
188     SpeculatedType getJSConstantSpeculation(Node* node)
189     {
190         return speculationFromValue(node->valueOfJSConstant(m_codeBlock));
191     }
192     
193     AddSpeculationMode addSpeculationMode(Node* add, bool leftShouldSpeculateInteger, bool rightShouldSpeculateInteger)
194     {
195         ASSERT(add->op() == ValueAdd || add->op() == ArithAdd || add->op() == ArithSub);
196         
197         Node* left = add->child1().node();
198         Node* right = add->child2().node();
199         
200         if (left->hasConstant())
201             return addImmediateShouldSpeculateInteger(add, rightShouldSpeculateInteger, left);
202         if (right->hasConstant())
203             return addImmediateShouldSpeculateInteger(add, leftShouldSpeculateInteger, right);
204         
205         return (leftShouldSpeculateInteger && rightShouldSpeculateInteger && add->canSpeculateInteger()) ? SpeculateInteger : DontSpeculateInteger;
206     }
207     
208     AddSpeculationMode valueAddSpeculationMode(Node* add)
209     {
210         return addSpeculationMode(add, add->child1()->shouldSpeculateIntegerExpectingDefined(), add->child2()->shouldSpeculateIntegerExpectingDefined());
211     }
212     
213     AddSpeculationMode arithAddSpeculationMode(Node* add)
214     {
215         return addSpeculationMode(add, add->child1()->shouldSpeculateIntegerForArithmetic(), add->child2()->shouldSpeculateIntegerForArithmetic());
216     }
217     
218     AddSpeculationMode addSpeculationMode(Node* add)
219     {
220         if (add->op() == ValueAdd)
221             return valueAddSpeculationMode(add);
222         
223         return arithAddSpeculationMode(add);
224     }
225     
226     bool addShouldSpeculateInteger(Node* add)
227     {
228         return addSpeculationMode(add) != DontSpeculateInteger;
229     }
230     
231     bool mulShouldSpeculateInteger(Node* mul)
232     {
233         ASSERT(mul->op() == ArithMul);
234         
235         Node* left = mul->child1().node();
236         Node* right = mul->child2().node();
237         
238         return Node::shouldSpeculateIntegerForArithmetic(left, right) && mul->canSpeculateInteger();
239     }
240     
241     bool negateShouldSpeculateInteger(Node* negate)
242     {
243         ASSERT(negate->op() == ArithNegate);
244         return negate->child1()->shouldSpeculateIntegerForArithmetic() && negate->canSpeculateInteger();
245     }
246     
247     // Helper methods to check nodes for constants.
248     bool isConstant(Node* node)
249     {
250         return node->hasConstant();
251     }
252     bool isJSConstant(Node* node)
253     {
254         return node->hasConstant();
255     }
256     bool isInt32Constant(Node* node)
257     {
258         return node->isInt32Constant(m_codeBlock);
259     }
260     bool isDoubleConstant(Node* node)
261     {
262         return node->isDoubleConstant(m_codeBlock);
263     }
264     bool isNumberConstant(Node* node)
265     {
266         return node->isNumberConstant(m_codeBlock);
267     }
268     bool isBooleanConstant(Node* node)
269     {
270         return node->isBooleanConstant(m_codeBlock);
271     }
272     bool isCellConstant(Node* node)
273     {
274         if (!isJSConstant(node))
275             return false;
276         JSValue value = valueOfJSConstant(node);
277         return value.isCell() && !!value;
278     }
279     bool isFunctionConstant(Node* node)
280     {
281         if (!isJSConstant(node))
282             return false;
283         if (!getJSFunction(valueOfJSConstant(node)))
284             return false;
285         return true;
286     }
287     bool isInternalFunctionConstant(Node* node)
288     {
289         if (!isJSConstant(node))
290             return false;
291         JSValue value = valueOfJSConstant(node);
292         if (!value.isCell() || !value)
293             return false;
294         JSCell* cell = value.asCell();
295         if (!cell->inherits(InternalFunction::info()))
296             return false;
297         return true;
298     }
299     // Helper methods get constant values from nodes.
300     JSValue valueOfJSConstant(Node* node)
301     {
302         return node->valueOfJSConstant(m_codeBlock);
303     }
304     int32_t valueOfInt32Constant(Node* node)
305     {
306         return valueOfJSConstant(node).asInt32();
307     }
308     double valueOfNumberConstant(Node* node)
309     {
310         return valueOfJSConstant(node).asNumber();
311     }
312     bool valueOfBooleanConstant(Node* node)
313     {
314         return valueOfJSConstant(node).asBoolean();
315     }
316     JSFunction* valueOfFunctionConstant(Node* node)
317     {
318         JSCell* function = getJSFunction(valueOfJSConstant(node));
319         ASSERT(function);
320         return jsCast<JSFunction*>(function);
321     }
322
323     static const char *opName(NodeType);
324     
325     StructureSet* addStructureSet(const StructureSet& structureSet)
326     {
327         ASSERT(structureSet.size());
328         m_structureSet.append(structureSet);
329         return &m_structureSet.last();
330     }
331     
332     StructureTransitionData* addStructureTransitionData(const StructureTransitionData& structureTransitionData)
333     {
334         m_structureTransitionData.append(structureTransitionData);
335         return &m_structureTransitionData.last();
336     }
337     
338     JSGlobalObject* globalObjectFor(CodeOrigin codeOrigin)
339     {
340         return m_codeBlock->globalObjectFor(codeOrigin);
341     }
342     
343     JSObject* globalThisObjectFor(CodeOrigin codeOrigin)
344     {
345         JSGlobalObject* object = globalObjectFor(codeOrigin);
346         return jsCast<JSObject*>(object->methodTable()->toThis(object, object->globalExec(), NotStrictMode));
347     }
348     
349     ScriptExecutable* executableFor(InlineCallFrame* inlineCallFrame)
350     {
351         if (!inlineCallFrame)
352             return m_codeBlock->ownerExecutable();
353         
354         return inlineCallFrame->executable.get();
355     }
356     
357     ScriptExecutable* executableFor(const CodeOrigin& codeOrigin)
358     {
359         return executableFor(codeOrigin.inlineCallFrame);
360     }
361     
362     CodeBlock* baselineCodeBlockFor(const CodeOrigin& codeOrigin)
363     {
364         return baselineCodeBlockForOriginAndBaselineCodeBlock(codeOrigin, m_profiledBlock);
365     }
366     
367     bool masqueradesAsUndefinedWatchpointIsStillValid(const CodeOrigin& codeOrigin)
368     {
369         return m_plan.watchpoints.isStillValid(
370             globalObjectFor(codeOrigin)->masqueradesAsUndefinedWatchpoint());
371     }
372     
373     bool hasGlobalExitSite(const CodeOrigin& codeOrigin, ExitKind exitKind)
374     {
375         return baselineCodeBlockFor(codeOrigin)->hasExitSite(FrequentExitSite(exitKind));
376     }
377     
378     bool hasExitSite(const CodeOrigin& codeOrigin, ExitKind exitKind)
379     {
380         return baselineCodeBlockFor(codeOrigin)->hasExitSite(FrequentExitSite(codeOrigin.bytecodeIndex, exitKind));
381     }
382     
383     int argumentsRegisterFor(const CodeOrigin& codeOrigin)
384     {
385         if (!codeOrigin.inlineCallFrame)
386             return m_codeBlock->argumentsRegister();
387         
388         return baselineCodeBlockForInlineCallFrame(
389             codeOrigin.inlineCallFrame)->argumentsRegister() +
390             codeOrigin.inlineCallFrame->stackOffset;
391     }
392     
393     int uncheckedArgumentsRegisterFor(const CodeOrigin& codeOrigin)
394     {
395         if (!codeOrigin.inlineCallFrame)
396             return m_codeBlock->uncheckedArgumentsRegister();
397         
398         CodeBlock* codeBlock = baselineCodeBlockForInlineCallFrame(
399             codeOrigin.inlineCallFrame);
400         if (!codeBlock->usesArguments())
401             return InvalidVirtualRegister;
402         
403         return codeBlock->argumentsRegister() +
404             codeOrigin.inlineCallFrame->stackOffset;
405     }
406     
407     int uncheckedActivationRegisterFor(const CodeOrigin&)
408     {
409         // This will ignore CodeOrigin because we don't inline code that uses activations.
410         // Hence for inlined call frames it will return the outermost code block's
411         // activation register. This method is only used to compare the result to a local
412         // to see if we're mucking with the activation register. Hence if we return the
413         // "wrong" activation register for the frame then it will compare false, which is
414         // what we wanted.
415         return m_codeBlock->uncheckedActivationRegister();
416     }
417     
418     ValueProfile* valueProfileFor(Node* node)
419     {
420         if (!node)
421             return 0;
422         
423         CodeBlock* profiledBlock = baselineCodeBlockFor(node->codeOrigin);
424         
425         if (node->op() == GetArgument)
426             return profiledBlock->valueProfileForArgument(operandToArgument(node->local()));
427         
428         if (node->hasLocal(*this)) {
429             if (m_form == SSA)
430                 return 0;
431             if (!operandIsArgument(node->local()))
432                 return 0;
433             int argument = operandToArgument(node->local());
434             if (node->variableAccessData() != m_arguments[argument]->variableAccessData())
435                 return 0;
436             return profiledBlock->valueProfileForArgument(argument);
437         }
438         
439         if (node->hasHeapPrediction())
440             return profiledBlock->valueProfileForBytecodeOffset(node->codeOrigin.bytecodeIndex);
441         
442         return 0;
443     }
444     
445     MethodOfGettingAValueProfile methodOfGettingAValueProfileFor(Node* node)
446     {
447         if (!node)
448             return MethodOfGettingAValueProfile();
449         
450         CodeBlock* profiledBlock = baselineCodeBlockFor(node->codeOrigin);
451         
452         if (node->op() == GetLocal) {
453             return MethodOfGettingAValueProfile::fromLazyOperand(
454                 profiledBlock,
455                 LazyOperandValueProfileKey(
456                     node->codeOrigin.bytecodeIndex, node->local()));
457         }
458         
459         return MethodOfGettingAValueProfile(valueProfileFor(node));
460     }
461     
462     bool needsActivation() const
463     {
464         return m_codeBlock->needsFullScopeChain() && m_codeBlock->codeType() != GlobalCode;
465     }
466     
467     bool usesArguments() const
468     {
469         return m_codeBlock->usesArguments();
470     }
471     
472     BlockIndex numBlocks() const { return m_blocks.size(); }
473     BasicBlock* block(BlockIndex blockIndex) const { return m_blocks[blockIndex].get(); }
474     BasicBlock* lastBlock() const { return block(numBlocks() - 1); }
475
476     void appendBlock(PassRefPtr<BasicBlock> basicBlock)
477     {
478         basicBlock->index = m_blocks.size();
479         m_blocks.append(basicBlock);
480     }
481     
482     void killBlock(BlockIndex blockIndex)
483     {
484         m_blocks[blockIndex].clear();
485     }
486     
487     void killBlock(BasicBlock* basicBlock)
488     {
489         killBlock(basicBlock->index);
490     }
491     
492     void killBlockAndItsContents(BasicBlock*);
493     
494     void killUnreachableBlocks();
495     
496     bool isPredictedNumerical(Node* node)
497     {
498         return isNumerical(node->child1().useKind()) && isNumerical(node->child2().useKind());
499     }
500     
501     // Note that a 'true' return does not actually mean that the ByVal access clobbers nothing.
502     // It really means that it will not clobber the entire world. It's still up to you to
503     // carefully consider things like:
504     // - PutByVal definitely changes the array it stores to, and may even change its length.
505     // - PutByOffset definitely changes the object it stores to.
506     // - and so on.
507     bool byValIsPure(Node* node)
508     {
509         switch (node->arrayMode().type()) {
510         case Array::Generic:
511             return false;
512         case Array::Int32:
513         case Array::Double:
514         case Array::Contiguous:
515         case Array::ArrayStorage:
516             return !node->arrayMode().isOutOfBounds();
517         case Array::SlowPutArrayStorage:
518             return !node->arrayMode().mayStoreToHole();
519         case Array::String:
520             return node->op() == GetByVal && node->arrayMode().isInBounds();
521 #if USE(JSVALUE32_64)
522         case Array::Arguments:
523             if (node->op() == GetByVal)
524                 return true;
525             return false;
526 #endif // USE(JSVALUE32_64)
527         default:
528             return true;
529         }
530     }
531     
532     bool clobbersWorld(Node* node)
533     {
534         if (node->flags() & NodeClobbersWorld)
535             return true;
536         if (!(node->flags() & NodeMightClobber))
537             return false;
538         switch (node->op()) {
539         case ValueAdd:
540         case CompareLess:
541         case CompareLessEq:
542         case CompareGreater:
543         case CompareGreaterEq:
544         case CompareEq:
545             return !isPredictedNumerical(node);
546         case GetByVal:
547         case PutByVal:
548         case PutByValAlias:
549             return !byValIsPure(node);
550         case ToString:
551             switch (node->child1().useKind()) {
552             case StringObjectUse:
553             case StringOrStringObjectUse:
554                 return false;
555             case CellUse:
556             case UntypedUse:
557                 return true;
558             default:
559                 RELEASE_ASSERT_NOT_REACHED();
560                 return true;
561             }
562         default:
563             RELEASE_ASSERT_NOT_REACHED();
564             return true; // If by some oddity we hit this case in release build it's safer to have CSE assume the worst.
565         }
566     }
567     
568     void determineReachability();
569     void resetReachability();
570     
571     void resetExitStates();
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)
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);
612     }
613     
614     void voteNode(Edge edge, unsigned ballot)
615     {
616         voteNode(edge.node(), ballot);
617     }
618     
619     void voteChildren(Node* node, unsigned ballot)
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);
627             }
628             return;
629         }
630         
631         if (!node->child1())
632             return;
633         voteNode(node->child1(), ballot);
634         if (!node->child2())
635             return;
636         voteNode(node->child2(), ballot);
637         if (!node->child3())
638             return;
639         voteNode(node->child3(), ballot);
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 clearReplacements();
675     void initializeNodeOwners();
676     
677     void getBlocksInDepthFirstOrder(Vector<BasicBlock*>& result);
678     
679     Profiler::Compilation* compilation() { return m_plan.compilation.get(); }
680     
681     DesiredIdentifiers& identifiers() { return m_plan.identifiers; }
682     DesiredWatchpoints& watchpoints() { return m_plan.watchpoints; }
683     DesiredStructureChains& chains() { return m_plan.chains; }
684     
685     VM& m_vm;
686     Plan& m_plan;
687     CodeBlock* m_codeBlock;
688     CodeBlock* m_profiledBlock;
689     
690     NodeAllocator& m_allocator;
691
692     Vector< RefPtr<BasicBlock> , 8> m_blocks;
693     Vector<Edge, 16> m_varArgChildren;
694     Vector<StorageAccessData> m_storageAccessData;
695     Vector<Node*, 8> m_arguments;
696     SegmentedVector<VariableAccessData, 16> m_variableAccessData;
697     SegmentedVector<ArgumentPosition, 8> m_argumentPositions;
698     SegmentedVector<StructureSet, 16> m_structureSet;
699     SegmentedVector<StructureTransitionData, 8> m_structureTransitionData;
700     SegmentedVector<NewArrayBufferData, 4> m_newArrayBufferData;
701     SegmentedVector<SwitchData, 4> m_switchData;
702     bool m_hasArguments;
703     HashSet<ExecutableBase*> m_executablesWhoseArgumentsEscaped;
704     BitVector m_preservedVars;
705     BitVector m_lazyVars;
706     Dominators m_dominators;
707     NaturalLoops m_naturalLoops;
708     unsigned m_localVars;
709     unsigned m_parameterSlots;
710     
711     OptimizationFixpointState m_fixpointState;
712     GraphForm m_form;
713     UnificationState m_unificationState;
714     RefCountState m_refCountState;
715 private:
716     
717     void handleSuccessor(Vector<BasicBlock*, 16>& worklist, BasicBlock*, BasicBlock* successor);
718     void addForDepthFirstSort(Vector<BasicBlock*>& result, Vector<BasicBlock*, 16>& worklist, HashSet<BasicBlock*>& seen, BasicBlock*);
719     
720     AddSpeculationMode addImmediateShouldSpeculateInteger(Node* add, bool variableShouldSpeculateInteger, Node* immediate)
721     {
722         ASSERT(immediate->hasConstant());
723         
724         JSValue immediateValue = immediate->valueOfJSConstant(m_codeBlock);
725         if (!immediateValue.isNumber())
726             return DontSpeculateInteger;
727         
728         if (!variableShouldSpeculateInteger)
729             return DontSpeculateInteger;
730         
731         if (immediateValue.isInt32())
732             return add->canSpeculateInteger() ? SpeculateInteger : DontSpeculateInteger;
733         
734         double doubleImmediate = immediateValue.asDouble();
735         const double twoToThe48 = 281474976710656.0;
736         if (doubleImmediate < -twoToThe48 || doubleImmediate > twoToThe48)
737             return DontSpeculateInteger;
738         
739         return nodeCanTruncateInteger(add->arithNodeFlags()) ? SpeculateIntegerAndTruncateConstants : DontSpeculateInteger;
740     }
741     
742     bool mulImmediateShouldSpeculateInteger(Node* mul, Node* variable, Node* immediate)
743     {
744         ASSERT(immediate->hasConstant());
745         
746         JSValue immediateValue = immediate->valueOfJSConstant(m_codeBlock);
747         if (!immediateValue.isInt32())
748             return false;
749         
750         if (!variable->shouldSpeculateIntegerForArithmetic())
751             return false;
752         
753         int32_t intImmediate = immediateValue.asInt32();
754         // Doubles have a 53 bit mantissa so we expect a multiplication of 2^31 (the highest
755         // magnitude possible int32 value) and any value less than 2^22 to not result in any
756         // rounding in a double multiplication - hence it will be equivalent to an integer
757         // multiplication, if we are doing int32 truncation afterwards (which is what
758         // canSpeculateInteger() implies).
759         const int32_t twoToThe22 = 1 << 22;
760         if (intImmediate <= -twoToThe22 || intImmediate >= twoToThe22)
761             return mul->canSpeculateInteger() && !nodeMayOverflow(mul->arithNodeFlags());
762
763         return mul->canSpeculateInteger();
764     }
765 };
766
767 #define DFG_NODE_DO_TO_CHILDREN(graph, node, thingToDo) do {            \
768         Node* _node = (node);                                           \
769         if (_node->flags() & NodeHasVarArgs) {                          \
770             for (unsigned _childIdx = _node->firstChild();              \
771                 _childIdx < _node->firstChild() + _node->numChildren(); \
772                 _childIdx++) {                                          \
773                 if (!!(graph).m_varArgChildren[_childIdx])              \
774                     thingToDo(_node, (graph).m_varArgChildren[_childIdx]); \
775             }                                                           \
776         } else {                                                        \
777             if (!_node->child1()) {                                     \
778                 ASSERT(                                                 \
779                     !_node->child2()                                    \
780                     && !_node->child3());                               \
781                 break;                                                  \
782             }                                                           \
783             thingToDo(_node, _node->child1());                          \
784                                                                         \
785             if (!_node->child2()) {                                     \
786                 ASSERT(!_node->child3());                               \
787                 break;                                                  \
788             }                                                           \
789             thingToDo(_node, _node->child2());                          \
790                                                                         \
791             if (!_node->child3())                                       \
792                 break;                                                  \
793             thingToDo(_node, _node->child3());                          \
794         }                                                               \
795     } while (false)
796
797 } } // namespace JSC::DFG
798
799 #endif
800 #endif