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