9eac443f6f2bf3612a095c0a5220d9685e4e5339
[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     void convertToConstant(Node* node, JSValue value)
155     {
156         convertToConstant(node, m_codeBlock->addOrFindConstant(value));
157     }
158
159     // CodeBlock is optional, but may allow additional information to be dumped (e.g. Identifier names).
160     void dump(PrintStream& = WTF::dataFile(), DumpContext* = 0);
161     enum PhiNodeDumpMode { DumpLivePhisOnly, DumpAllPhis };
162     void dumpBlockHeader(PrintStream&, const char* prefix, BasicBlock*, PhiNodeDumpMode, DumpContext* context);
163     void dump(PrintStream&, Edge);
164     void dump(PrintStream&, const char* prefix, Node*, DumpContext* = 0);
165     static int amountOfNodeWhiteSpace(Node*);
166     static void printNodeWhiteSpace(PrintStream&, Node*);
167
168     // Dump the code origin of the given node as a diff from the code origin of the
169     // preceding node. Returns true if anything was printed.
170     bool dumpCodeOrigin(PrintStream&, const char* prefix, Node* previousNode, Node* currentNode, DumpContext* context);
171
172     SpeculatedType getJSConstantSpeculation(Node* node)
173     {
174         return speculationFromValue(node->valueOfJSConstant(m_codeBlock));
175     }
176     
177     AddSpeculationMode addSpeculationMode(Node* add, bool leftShouldSpeculateInteger, bool rightShouldSpeculateInteger)
178     {
179         ASSERT(add->op() == ValueAdd || add->op() == ArithAdd || add->op() == ArithSub);
180         
181         Node* left = add->child1().node();
182         Node* right = add->child2().node();
183         
184         if (left->hasConstant())
185             return addImmediateShouldSpeculateInteger(add, rightShouldSpeculateInteger, left);
186         if (right->hasConstant())
187             return addImmediateShouldSpeculateInteger(add, leftShouldSpeculateInteger, right);
188         
189         return (leftShouldSpeculateInteger && rightShouldSpeculateInteger && add->canSpeculateInteger()) ? SpeculateInteger : DontSpeculateInteger;
190     }
191     
192     AddSpeculationMode valueAddSpeculationMode(Node* add)
193     {
194         return addSpeculationMode(add, add->child1()->shouldSpeculateIntegerExpectingDefined(), add->child2()->shouldSpeculateIntegerExpectingDefined());
195     }
196     
197     AddSpeculationMode arithAddSpeculationMode(Node* add)
198     {
199         return addSpeculationMode(add, add->child1()->shouldSpeculateIntegerForArithmetic(), add->child2()->shouldSpeculateIntegerForArithmetic());
200     }
201     
202     AddSpeculationMode addSpeculationMode(Node* add)
203     {
204         if (add->op() == ValueAdd)
205             return valueAddSpeculationMode(add);
206         
207         return arithAddSpeculationMode(add);
208     }
209     
210     bool addShouldSpeculateInteger(Node* add)
211     {
212         return addSpeculationMode(add) != DontSpeculateInteger;
213     }
214     
215     bool mulShouldSpeculateInteger(Node* mul)
216     {
217         ASSERT(mul->op() == ArithMul);
218         
219         Node* left = mul->child1().node();
220         Node* right = mul->child2().node();
221         
222         return Node::shouldSpeculateIntegerForArithmetic(left, right) && mul->canSpeculateInteger();
223     }
224     
225     bool negateShouldSpeculateInteger(Node* negate)
226     {
227         ASSERT(negate->op() == ArithNegate);
228         return negate->child1()->shouldSpeculateIntegerForArithmetic() && negate->canSpeculateInteger();
229     }
230     
231     // Helper methods to check nodes for constants.
232     bool isConstant(Node* node)
233     {
234         return node->hasConstant();
235     }
236     bool isJSConstant(Node* node)
237     {
238         return node->hasConstant();
239     }
240     bool isInt32Constant(Node* node)
241     {
242         return node->isInt32Constant(m_codeBlock);
243     }
244     bool isDoubleConstant(Node* node)
245     {
246         return node->isDoubleConstant(m_codeBlock);
247     }
248     bool isNumberConstant(Node* node)
249     {
250         return node->isNumberConstant(m_codeBlock);
251     }
252     bool isBooleanConstant(Node* node)
253     {
254         return node->isBooleanConstant(m_codeBlock);
255     }
256     bool isCellConstant(Node* node)
257     {
258         if (!isJSConstant(node))
259             return false;
260         JSValue value = valueOfJSConstant(node);
261         return value.isCell() && !!value;
262     }
263     bool isFunctionConstant(Node* node)
264     {
265         if (!isJSConstant(node))
266             return false;
267         if (!getJSFunction(valueOfJSConstant(node)))
268             return false;
269         return true;
270     }
271     bool isInternalFunctionConstant(Node* node)
272     {
273         if (!isJSConstant(node))
274             return false;
275         JSValue value = valueOfJSConstant(node);
276         if (!value.isCell() || !value)
277             return false;
278         JSCell* cell = value.asCell();
279         if (!cell->inherits(&InternalFunction::s_info))
280             return false;
281         return true;
282     }
283     // Helper methods get constant values from nodes.
284     JSValue valueOfJSConstant(Node* node)
285     {
286         return node->valueOfJSConstant(m_codeBlock);
287     }
288     int32_t valueOfInt32Constant(Node* node)
289     {
290         return valueOfJSConstant(node).asInt32();
291     }
292     double valueOfNumberConstant(Node* node)
293     {
294         return valueOfJSConstant(node).asNumber();
295     }
296     bool valueOfBooleanConstant(Node* node)
297     {
298         return valueOfJSConstant(node).asBoolean();
299     }
300     JSFunction* valueOfFunctionConstant(Node* node)
301     {
302         JSCell* function = getJSFunction(valueOfJSConstant(node));
303         ASSERT(function);
304         return jsCast<JSFunction*>(function);
305     }
306
307     static const char *opName(NodeType);
308     
309     StructureSet* addStructureSet(const StructureSet& structureSet)
310     {
311         ASSERT(structureSet.size());
312         m_structureSet.append(structureSet);
313         return &m_structureSet.last();
314     }
315     
316     StructureTransitionData* addStructureTransitionData(const StructureTransitionData& structureTransitionData)
317     {
318         m_structureTransitionData.append(structureTransitionData);
319         return &m_structureTransitionData.last();
320     }
321     
322     JSGlobalObject* globalObjectFor(CodeOrigin codeOrigin)
323     {
324         return m_codeBlock->globalObjectFor(codeOrigin);
325     }
326     
327     JSObject* globalThisObjectFor(CodeOrigin codeOrigin)
328     {
329         JSGlobalObject* object = globalObjectFor(codeOrigin);
330         return jsCast<JSObject*>(object->methodTable()->toThis(object, object->globalExec(), NotStrictMode));
331     }
332     
333     ScriptExecutable* executableFor(InlineCallFrame* inlineCallFrame)
334     {
335         if (!inlineCallFrame)
336             return m_codeBlock->ownerExecutable();
337         
338         return inlineCallFrame->executable.get();
339     }
340     
341     ScriptExecutable* executableFor(const CodeOrigin& codeOrigin)
342     {
343         return executableFor(codeOrigin.inlineCallFrame);
344     }
345     
346     CodeBlock* baselineCodeBlockFor(const CodeOrigin& codeOrigin)
347     {
348         return baselineCodeBlockForOriginAndBaselineCodeBlock(codeOrigin, m_profiledBlock);
349     }
350     
351     bool masqueradesAsUndefinedWatchpointIsStillValid(const CodeOrigin& codeOrigin)
352     {
353         return m_plan.watchpoints.isStillValid(
354             globalObjectFor(codeOrigin)->masqueradesAsUndefinedWatchpoint());
355     }
356     
357     bool hasGlobalExitSite(const CodeOrigin& codeOrigin, ExitKind exitKind)
358     {
359         return baselineCodeBlockFor(codeOrigin)->hasExitSite(FrequentExitSite(exitKind));
360     }
361     
362     bool hasExitSite(const CodeOrigin& codeOrigin, ExitKind exitKind)
363     {
364         return baselineCodeBlockFor(codeOrigin)->hasExitSite(FrequentExitSite(codeOrigin.bytecodeIndex, exitKind));
365     }
366     
367     int argumentsRegisterFor(const CodeOrigin& codeOrigin)
368     {
369         if (!codeOrigin.inlineCallFrame)
370             return m_codeBlock->argumentsRegister();
371         
372         return baselineCodeBlockForInlineCallFrame(
373             codeOrigin.inlineCallFrame)->argumentsRegister() +
374             codeOrigin.inlineCallFrame->stackOffset;
375     }
376     
377     int uncheckedArgumentsRegisterFor(const CodeOrigin& codeOrigin)
378     {
379         if (!codeOrigin.inlineCallFrame)
380             return m_codeBlock->uncheckedArgumentsRegister();
381         
382         CodeBlock* codeBlock = baselineCodeBlockForInlineCallFrame(
383             codeOrigin.inlineCallFrame);
384         if (!codeBlock->usesArguments())
385             return InvalidVirtualRegister;
386         
387         return codeBlock->argumentsRegister() +
388             codeOrigin.inlineCallFrame->stackOffset;
389     }
390     
391     int uncheckedActivationRegisterFor(const CodeOrigin&)
392     {
393         // This will ignore CodeOrigin because we don't inline code that uses activations.
394         // Hence for inlined call frames it will return the outermost code block's
395         // activation register. This method is only used to compare the result to a local
396         // to see if we're mucking with the activation register. Hence if we return the
397         // "wrong" activation register for the frame then it will compare false, which is
398         // what we wanted.
399         return m_codeBlock->uncheckedActivationRegister();
400     }
401     
402     ValueProfile* valueProfileFor(Node* node)
403     {
404         if (!node)
405             return 0;
406         
407         CodeBlock* profiledBlock = baselineCodeBlockFor(node->codeOrigin);
408         
409         if (node->op() == GetArgument)
410             return profiledBlock->valueProfileForArgument(operandToArgument(node->local()));
411         
412         if (node->hasLocal(*this)) {
413             if (m_form == SSA)
414                 return 0;
415             if (!operandIsArgument(node->local()))
416                 return 0;
417             int argument = operandToArgument(node->local());
418             if (node->variableAccessData() != m_arguments[argument]->variableAccessData())
419                 return 0;
420             return profiledBlock->valueProfileForArgument(argument);
421         }
422         
423         if (node->hasHeapPrediction())
424             return profiledBlock->valueProfileForBytecodeOffset(node->codeOrigin.bytecodeIndex);
425         
426         return 0;
427     }
428     
429     MethodOfGettingAValueProfile methodOfGettingAValueProfileFor(Node* node)
430     {
431         if (!node)
432             return MethodOfGettingAValueProfile();
433         
434         CodeBlock* profiledBlock = baselineCodeBlockFor(node->codeOrigin);
435         
436         if (node->op() == GetLocal) {
437             return MethodOfGettingAValueProfile::fromLazyOperand(
438                 profiledBlock,
439                 LazyOperandValueProfileKey(
440                     node->codeOrigin.bytecodeIndex, node->local()));
441         }
442         
443         return MethodOfGettingAValueProfile(valueProfileFor(node));
444     }
445     
446     bool needsActivation() const
447     {
448         return m_codeBlock->needsFullScopeChain() && m_codeBlock->codeType() != GlobalCode;
449     }
450     
451     bool usesArguments() const
452     {
453         return m_codeBlock->usesArguments();
454     }
455     
456     BlockIndex numBlocks() const { return m_blocks.size(); }
457     BasicBlock* block(BlockIndex blockIndex) const { return m_blocks[blockIndex].get(); }
458     BasicBlock* lastBlock() const { return block(numBlocks() - 1); }
459
460     void appendBlock(PassRefPtr<BasicBlock> basicBlock)
461     {
462         basicBlock->index = m_blocks.size();
463         m_blocks.append(basicBlock);
464     }
465     
466     void killBlock(BlockIndex blockIndex)
467     {
468         m_blocks[blockIndex].clear();
469     }
470     
471     void killBlock(BasicBlock* basicBlock)
472     {
473         killBlock(basicBlock->index);
474     }
475     
476     bool isPredictedNumerical(Node* node)
477     {
478         return isNumerical(node->child1().useKind()) && isNumerical(node->child2().useKind());
479     }
480     
481     // Note that a 'true' return does not actually mean that the ByVal access clobbers nothing.
482     // It really means that it will not clobber the entire world. It's still up to you to
483     // carefully consider things like:
484     // - PutByVal definitely changes the array it stores to, and may even change its length.
485     // - PutByOffset definitely changes the object it stores to.
486     // - and so on.
487     bool byValIsPure(Node* node)
488     {
489         switch (node->arrayMode().type()) {
490         case Array::Generic:
491             return false;
492         case Array::Int32:
493         case Array::Double:
494         case Array::Contiguous:
495         case Array::ArrayStorage:
496             return !node->arrayMode().isOutOfBounds();
497         case Array::SlowPutArrayStorage:
498             return !node->arrayMode().mayStoreToHole();
499         case Array::String:
500             return node->op() == GetByVal && node->arrayMode().isInBounds();
501 #if USE(JSVALUE32_64)
502         case Array::Arguments:
503             if (node->op() == GetByVal)
504                 return true;
505             return false;
506 #endif // USE(JSVALUE32_64)
507         default:
508             return true;
509         }
510     }
511     
512     bool clobbersWorld(Node* node)
513     {
514         if (node->flags() & NodeClobbersWorld)
515             return true;
516         if (!(node->flags() & NodeMightClobber))
517             return false;
518         switch (node->op()) {
519         case ValueAdd:
520         case CompareLess:
521         case CompareLessEq:
522         case CompareGreater:
523         case CompareGreaterEq:
524         case CompareEq:
525             return !isPredictedNumerical(node);
526         case GetByVal:
527         case PutByVal:
528         case PutByValAlias:
529             return !byValIsPure(node);
530         case ToString:
531             switch (node->child1().useKind()) {
532             case StringObjectUse:
533             case StringOrStringObjectUse:
534                 return false;
535             case CellUse:
536             case UntypedUse:
537                 return true;
538             default:
539                 RELEASE_ASSERT_NOT_REACHED();
540                 return true;
541             }
542         default:
543             RELEASE_ASSERT_NOT_REACHED();
544             return true; // If by some oddity we hit this case in release build it's safer to have CSE assume the worst.
545         }
546     }
547     
548     void determineReachability();
549     void resetReachability();
550     
551     void resetExitStates();
552     
553     unsigned varArgNumChildren(Node* node)
554     {
555         ASSERT(node->flags() & NodeHasVarArgs);
556         return node->numChildren();
557     }
558     
559     unsigned numChildren(Node* node)
560     {
561         if (node->flags() & NodeHasVarArgs)
562             return varArgNumChildren(node);
563         return AdjacencyList::Size;
564     }
565     
566     Edge& varArgChild(Node* node, unsigned index)
567     {
568         ASSERT(node->flags() & NodeHasVarArgs);
569         return m_varArgChildren[node->firstChild() + index];
570     }
571     
572     Edge& child(Node* node, unsigned index)
573     {
574         if (node->flags() & NodeHasVarArgs)
575             return varArgChild(node, index);
576         return node->children.child(index);
577     }
578     
579     void voteNode(Node* node, unsigned ballot)
580     {
581         switch (node->op()) {
582         case ValueToInt32:
583         case UInt32ToNumber:
584             node = node->child1().node();
585             break;
586         default:
587             break;
588         }
589         
590         if (node->op() == GetLocal)
591             node->variableAccessData()->vote(ballot);
592     }
593     
594     void voteNode(Edge edge, unsigned ballot)
595     {
596         voteNode(edge.node(), ballot);
597     }
598     
599     void voteChildren(Node* node, unsigned ballot)
600     {
601         if (node->flags() & NodeHasVarArgs) {
602             for (unsigned childIdx = node->firstChild();
603                 childIdx < node->firstChild() + node->numChildren();
604                 childIdx++) {
605                 if (!!m_varArgChildren[childIdx])
606                     voteNode(m_varArgChildren[childIdx], ballot);
607             }
608             return;
609         }
610         
611         if (!node->child1())
612             return;
613         voteNode(node->child1(), ballot);
614         if (!node->child2())
615             return;
616         voteNode(node->child2(), ballot);
617         if (!node->child3())
618             return;
619         voteNode(node->child3(), ballot);
620     }
621     
622     template<typename T> // T = Node* or Edge
623     void substitute(BasicBlock& block, unsigned startIndexInBlock, T oldThing, T newThing)
624     {
625         for (unsigned indexInBlock = startIndexInBlock; indexInBlock < block.size(); ++indexInBlock) {
626             Node* node = block[indexInBlock];
627             if (node->flags() & NodeHasVarArgs) {
628                 for (unsigned childIdx = node->firstChild(); childIdx < node->firstChild() + node->numChildren(); ++childIdx) {
629                     if (!!m_varArgChildren[childIdx])
630                         compareAndSwap(m_varArgChildren[childIdx], oldThing, newThing);
631                 }
632                 continue;
633             }
634             if (!node->child1())
635                 continue;
636             compareAndSwap(node->children.child1(), oldThing, newThing);
637             if (!node->child2())
638                 continue;
639             compareAndSwap(node->children.child2(), oldThing, newThing);
640             if (!node->child3())
641                 continue;
642             compareAndSwap(node->children.child3(), oldThing, newThing);
643         }
644     }
645     
646     // Use this if you introduce a new GetLocal and you know that you introduced it *before*
647     // any GetLocals in the basic block.
648     // FIXME: it may be appropriate, in the future, to generalize this to handle GetLocals
649     // introduced anywhere in the basic block.
650     void substituteGetLocal(BasicBlock& block, unsigned startIndexInBlock, VariableAccessData* variableAccessData, Node* newGetLocal);
651     
652     void invalidateCFG();
653     
654     void clearReplacements();
655     void initializeNodeOwners();
656     
657     void getBlocksInDepthFirstOrder(Vector<BasicBlock*>& result);
658     
659     Profiler::Compilation* compilation() { return m_plan.compilation.get(); }
660     
661     DesiredIdentifiers& identifiers() { return m_plan.identifiers; }
662     DesiredWatchpoints& watchpoints() { return m_plan.watchpoints; }
663     DesiredStructureChains& chains() { return m_plan.chains; }
664     
665     VM& m_vm;
666     Plan& m_plan;
667     CodeBlock* m_codeBlock;
668     CodeBlock* m_profiledBlock;
669     
670     NodeAllocator& m_allocator;
671
672     Vector< RefPtr<BasicBlock> , 8> m_blocks;
673     Vector<Edge, 16> m_varArgChildren;
674     Vector<StorageAccessData> m_storageAccessData;
675     Vector<Node*, 8> m_arguments;
676     SegmentedVector<VariableAccessData, 16> m_variableAccessData;
677     SegmentedVector<ArgumentPosition, 8> m_argumentPositions;
678     SegmentedVector<StructureSet, 16> m_structureSet;
679     SegmentedVector<StructureTransitionData, 8> m_structureTransitionData;
680     SegmentedVector<NewArrayBufferData, 4> m_newArrayBufferData;
681     SegmentedVector<SwitchData, 4> m_switchData;
682     bool m_hasArguments;
683     HashSet<ExecutableBase*> m_executablesWhoseArgumentsEscaped;
684     BitVector m_preservedVars;
685     Dominators m_dominators;
686     NaturalLoops m_naturalLoops;
687     unsigned m_localVars;
688     unsigned m_parameterSlots;
689     
690     OptimizationFixpointState m_fixpointState;
691     GraphForm m_form;
692     UnificationState m_unificationState;
693     RefCountState m_refCountState;
694 private:
695     
696     void handleSuccessor(Vector<BasicBlock*, 16>& worklist, BasicBlock*, BasicBlock* successor);
697     void addForDepthFirstSort(Vector<BasicBlock*>& result, Vector<BasicBlock*, 16>& worklist, HashSet<BasicBlock*>& seen, BasicBlock*);
698     
699     AddSpeculationMode addImmediateShouldSpeculateInteger(Node* add, bool variableShouldSpeculateInteger, Node* immediate)
700     {
701         ASSERT(immediate->hasConstant());
702         
703         JSValue immediateValue = immediate->valueOfJSConstant(m_codeBlock);
704         if (!immediateValue.isNumber())
705             return DontSpeculateInteger;
706         
707         if (!variableShouldSpeculateInteger)
708             return DontSpeculateInteger;
709         
710         if (immediateValue.isInt32())
711             return add->canSpeculateInteger() ? SpeculateInteger : DontSpeculateInteger;
712         
713         double doubleImmediate = immediateValue.asDouble();
714         const double twoToThe48 = 281474976710656.0;
715         if (doubleImmediate < -twoToThe48 || doubleImmediate > twoToThe48)
716             return DontSpeculateInteger;
717         
718         return nodeCanTruncateInteger(add->arithNodeFlags()) ? SpeculateIntegerAndTruncateConstants : DontSpeculateInteger;
719     }
720     
721     bool mulImmediateShouldSpeculateInteger(Node* mul, Node* variable, Node* immediate)
722     {
723         ASSERT(immediate->hasConstant());
724         
725         JSValue immediateValue = immediate->valueOfJSConstant(m_codeBlock);
726         if (!immediateValue.isInt32())
727             return false;
728         
729         if (!variable->shouldSpeculateIntegerForArithmetic())
730             return false;
731         
732         int32_t intImmediate = immediateValue.asInt32();
733         // Doubles have a 53 bit mantissa so we expect a multiplication of 2^31 (the highest
734         // magnitude possible int32 value) and any value less than 2^22 to not result in any
735         // rounding in a double multiplication - hence it will be equivalent to an integer
736         // multiplication, if we are doing int32 truncation afterwards (which is what
737         // canSpeculateInteger() implies).
738         const int32_t twoToThe22 = 1 << 22;
739         if (intImmediate <= -twoToThe22 || intImmediate >= twoToThe22)
740             return mul->canSpeculateInteger() && !nodeMayOverflow(mul->arithNodeFlags());
741
742         return mul->canSpeculateInteger();
743     }
744 };
745
746 #define DFG_NODE_DO_TO_CHILDREN(graph, node, thingToDo) do {            \
747         Node* _node = (node);                                           \
748         if (_node->flags() & NodeHasVarArgs) {                          \
749             for (unsigned _childIdx = _node->firstChild();              \
750                 _childIdx < _node->firstChild() + _node->numChildren(); \
751                 _childIdx++) {                                          \
752                 if (!!(graph).m_varArgChildren[_childIdx])              \
753                     thingToDo(_node, (graph).m_varArgChildren[_childIdx]); \
754             }                                                           \
755         } else {                                                        \
756             if (!_node->child1()) {                                     \
757                 ASSERT(                                                 \
758                     !_node->child2()                                    \
759                     && !_node->child3());                               \
760                 break;                                                  \
761             }                                                           \
762             thingToDo(_node, _node->child1());                          \
763                                                                         \
764             if (!_node->child2()) {                                     \
765                 ASSERT(!_node->child3());                               \
766                 break;                                                  \
767             }                                                           \
768             thingToDo(_node, _node->child2());                          \
769                                                                         \
770             if (!_node->child3())                                       \
771                 break;                                                  \
772             thingToDo(_node, _node->child3());                          \
773         }                                                               \
774     } while (false)
775
776 } } // namespace JSC::DFG
777
778 #endif
779 #endif