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