1/*
2 * Copyright (C) 2011, 2012, 2013, 2014 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef DFGGraph_h
27#define DFGGraph_h
28
29#if ENABLE(DFG_JIT)
30
31#include "AssemblyHelpers.h"
32#include "CodeBlock.h"
33#include "DFGArgumentPosition.h"
34#include "DFGBasicBlock.h"
35#include "DFGDominators.h"
36#include "DFGLongLivedState.h"
37#include "DFGNaturalLoops.h"
38#include "DFGNode.h"
39#include "DFGNodeAllocator.h"
40#include "DFGPlan.h"
41#include "DFGScannable.h"
42#include "JSStack.h"
43#include "MethodOfGettingAValueProfile.h"
44#include <unordered_map>
45#include <wtf/BitVector.h>
46#include <wtf/HashMap.h>
47#include <wtf/Vector.h>
48#include <wtf/StdLibExtras.h>
49
50namespace JSC {
51
52class CodeBlock;
53class ExecState;
54
55namespace DFG {
56
57struct StorageAccessData {
58    PropertyOffset offset;
59    unsigned identifierNumber;
60};
61
62struct InlineVariableData {
63    InlineCallFrame* inlineCallFrame;
64    unsigned argumentPositionStart;
65    VariableAccessData* calleeVariable;
66};
67
68enum AddSpeculationMode {
69    DontSpeculateInt32,
70    SpeculateInt32AndTruncateConstants,
71    SpeculateInt32
72};
73
74//
75// === Graph ===
76//
77// The order may be significant for nodes with side-effects (property accesses, value conversions).
78// Nodes that are 'dead' remain in the vector with refCount 0.
79class Graph : public virtual Scannable {
80public:
81    Graph(VM&, Plan&, LongLivedState&);
82    ~Graph();
83
84    void changeChild(Edge& edge, Node* newNode)
85    {
86        edge.setNode(newNode);
87    }
88
89    void changeEdge(Edge& edge, Edge newEdge)
90    {
91        edge = newEdge;
92    }
93
94    void compareAndSwap(Edge& edge, Node* oldNode, Node* newNode)
95    {
96        if (edge.node() != oldNode)
97            return;
98        changeChild(edge, newNode);
99    }
100
101    void compareAndSwap(Edge& edge, Edge oldEdge, Edge newEdge)
102    {
103        if (edge != oldEdge)
104            return;
105        changeEdge(edge, newEdge);
106    }
107
108    void performSubstitution(Node* node)
109    {
110        if (node->flags() & NodeHasVarArgs) {
111            for (unsigned childIdx = node->firstChild(); childIdx < node->firstChild() + node->numChildren(); childIdx++)
112                performSubstitutionForEdge(m_varArgChildren[childIdx]);
113        } else {
114            performSubstitutionForEdge(node->child1());
115            performSubstitutionForEdge(node->child2());
116            performSubstitutionForEdge(node->child3());
117        }
118    }
119
120    void performSubstitutionForEdge(Edge& child)
121    {
122        // Check if this operand is actually unused.
123        if (!child)
124            return;
125
126        // Check if there is any replacement.
127        Node* replacement = child->misc.replacement;
128        if (!replacement)
129            return;
130
131        child.setNode(replacement);
132
133        // There is definitely a replacement. Assert that the replacement does not
134        // have a replacement.
135        ASSERT(!child->misc.replacement);
136    }
137
138    template<typename... Params>
139    Node* addNode(SpeculatedType type, Params... params)
140    {
141        Node* node = new (m_allocator) Node(params...);
142        node->predict(type);
143        return node;
144    }
145
146    void dethread();
147
148    void convertToConstant(Node* node, unsigned constantNumber)
149    {
150        if (node->op() == GetLocal)
151            dethread();
152        else
153            ASSERT(!node->hasVariableAccessData(*this));
154        node->convertToConstant(constantNumber);
155    }
156
157    unsigned constantRegisterForConstant(JSValue value)
158    {
159        unsigned constantRegister;
160        if (!m_codeBlock->findConstant(value, constantRegister)) {
161            constantRegister = m_codeBlock->addConstantLazily();
162            initializeLazyWriteBarrierForConstant(
163                m_plan.writeBarriers,
164                m_codeBlock->constants()[constantRegister],
165                m_codeBlock,
166                constantRegister,
167                m_codeBlock->ownerExecutable(),
168                value);
169        }
170        return constantRegister;
171    }
172
173    void convertToConstant(Node* node, JSValue value)
174    {
175        if (value.isObject())
176            node->convertToWeakConstant(value.asCell());
177        else
178            convertToConstant(node, constantRegisterForConstant(value));
179    }
180
181    // CodeBlock is optional, but may allow additional information to be dumped (e.g. Identifier names).
182    void dump(PrintStream& = WTF::dataFile(), DumpContext* = 0);
183    enum PhiNodeDumpMode { DumpLivePhisOnly, DumpAllPhis };
184    void dumpBlockHeader(PrintStream&, const char* prefix, BasicBlock*, PhiNodeDumpMode, DumpContext*);
185    void dump(PrintStream&, Edge);
186    void dump(PrintStream&, const char* prefix, Node*, DumpContext* = 0);
187    static int amountOfNodeWhiteSpace(Node*);
188    static void printNodeWhiteSpace(PrintStream&, Node*);
189
190    // Dump the code origin of the given node as a diff from the code origin of the
191    // preceding node. Returns true if anything was printed.
192    bool dumpCodeOrigin(PrintStream&, const char* prefix, Node* previousNode, Node* currentNode, DumpContext*);
193
194    SpeculatedType getJSConstantSpeculation(Node* node)
195    {
196        return speculationFromValue(node->valueOfJSConstant(m_codeBlock));
197    }
198
199    AddSpeculationMode addSpeculationMode(Node* add, bool leftShouldSpeculateInt32, bool rightShouldSpeculateInt32, PredictionPass pass)
200    {
201        ASSERT(add->op() == ValueAdd || add->op() == ArithAdd || add->op() == ArithSub);
202
203        RareCaseProfilingSource source = add->sourceFor(pass);
204
205        Node* left = add->child1().node();
206        Node* right = add->child2().node();
207
208        if (left->hasConstant())
209            return addImmediateShouldSpeculateInt32(add, rightShouldSpeculateInt32, left, source);
210        if (right->hasConstant())
211            return addImmediateShouldSpeculateInt32(add, leftShouldSpeculateInt32, right, source);
212
213        return (leftShouldSpeculateInt32 && rightShouldSpeculateInt32 && add->canSpeculateInt32(source)) ? SpeculateInt32 : DontSpeculateInt32;
214    }
215
216    AddSpeculationMode valueAddSpeculationMode(Node* add, PredictionPass pass)
217    {
218        return addSpeculationMode(
219            add,
220            add->child1()->shouldSpeculateInt32OrBooleanExpectingDefined(),
221            add->child2()->shouldSpeculateInt32OrBooleanExpectingDefined(),
222            pass);
223    }
224
225    AddSpeculationMode arithAddSpeculationMode(Node* add, PredictionPass pass)
226    {
227        return addSpeculationMode(
228            add,
229            add->child1()->shouldSpeculateInt32OrBooleanForArithmetic(),
230            add->child2()->shouldSpeculateInt32OrBooleanForArithmetic(),
231            pass);
232    }
233
234    AddSpeculationMode addSpeculationMode(Node* add, PredictionPass pass)
235    {
236        if (add->op() == ValueAdd)
237            return valueAddSpeculationMode(add, pass);
238
239        return arithAddSpeculationMode(add, pass);
240    }
241
242    bool addShouldSpeculateInt32(Node* add, PredictionPass pass)
243    {
244        return addSpeculationMode(add, pass) != DontSpeculateInt32;
245    }
246
247    bool addShouldSpeculateMachineInt(Node* add)
248    {
249        if (!enableInt52())
250            return false;
251
252        Node* left = add->child1().node();
253        Node* right = add->child2().node();
254
255        bool speculation;
256        if (add->op() == ValueAdd)
257            speculation = Node::shouldSpeculateMachineInt(left, right);
258        else
259            speculation = Node::shouldSpeculateMachineInt(left, right);
260
261        return speculation && !hasExitSite(add, Int52Overflow);
262    }
263
264    bool mulShouldSpeculateInt32(Node* mul, PredictionPass pass)
265    {
266        ASSERT(mul->op() == ArithMul);
267
268        Node* left = mul->child1().node();
269        Node* right = mul->child2().node();
270
271        return Node::shouldSpeculateInt32OrBooleanForArithmetic(left, right)
272            && mul->canSpeculateInt32(mul->sourceFor(pass));
273    }
274
275    bool mulShouldSpeculateMachineInt(Node* mul, PredictionPass pass)
276    {
277        ASSERT(mul->op() == ArithMul);
278
279        if (!enableInt52())
280            return false;
281
282        Node* left = mul->child1().node();
283        Node* right = mul->child2().node();
284
285        return Node::shouldSpeculateMachineInt(left, right)
286            && mul->canSpeculateInt52(pass)
287            && !hasExitSite(mul, Int52Overflow);
288    }
289
290    bool negateShouldSpeculateInt32(Node* negate, PredictionPass pass)
291    {
292        ASSERT(negate->op() == ArithNegate);
293        return negate->child1()->shouldSpeculateInt32OrBooleanForArithmetic()
294            && negate->canSpeculateInt32(pass);
295    }
296
297    bool negateShouldSpeculateMachineInt(Node* negate, PredictionPass pass)
298    {
299        ASSERT(negate->op() == ArithNegate);
300        if (!enableInt52())
301            return false;
302        return negate->child1()->shouldSpeculateMachineInt()
303            && !hasExitSite(negate, Int52Overflow)
304            && negate->canSpeculateInt52(pass);
305    }
306
307    VirtualRegister bytecodeRegisterForArgument(CodeOrigin codeOrigin, int argument)
308    {
309        return VirtualRegister(
310            codeOrigin.inlineCallFrame->stackOffset +
311            baselineCodeBlockFor(codeOrigin)->argumentIndexAfterCapture(argument));
312    }
313
314    // Helper methods to check nodes for constants.
315    bool isConstant(Node* node)
316    {
317        return node->hasConstant();
318    }
319    bool isJSConstant(Node* node)
320    {
321        return node->hasConstant();
322    }
323    bool isInt32Constant(Node* node)
324    {
325        return node->isInt32Constant(m_codeBlock);
326    }
327    bool isDoubleConstant(Node* node)
328    {
329        return node->isDoubleConstant(m_codeBlock);
330    }
331    bool isNumberConstant(Node* node)
332    {
333        return node->isNumberConstant(m_codeBlock);
334    }
335    bool isMachineIntConstant(Node* node)
336    {
337        return node->isMachineIntConstant(m_codeBlock);
338    }
339    bool isBooleanConstant(Node* node)
340    {
341        return node->isBooleanConstant(m_codeBlock);
342    }
343    bool isCellConstant(Node* node)
344    {
345        if (!isJSConstant(node))
346            return false;
347        JSValue value = valueOfJSConstant(node);
348        return value.isCell() && !!value;
349    }
350    bool isFunctionConstant(Node* node)
351    {
352        if (!isJSConstant(node))
353            return false;
354        if (!getJSFunction(valueOfJSConstant(node)))
355            return false;
356        return true;
357    }
358    bool isInternalFunctionConstant(Node* node)
359    {
360        if (!isJSConstant(node))
361            return false;
362        JSValue value = valueOfJSConstant(node);
363        if (!value.isCell() || !value)
364            return false;
365        JSCell* cell = value.asCell();
366        if (!cell->inherits(InternalFunction::info()))
367            return false;
368        return true;
369    }
370    // Helper methods get constant values from nodes.
371    JSValue valueOfJSConstant(Node* node)
372    {
373        return node->valueOfJSConstant(m_codeBlock);
374    }
375    int32_t valueOfInt32Constant(Node* node)
376    {
377        JSValue value = valueOfJSConstant(node);
378        if (!value.isInt32()) {
379            dataLog("Value isn't int32: ", value, "\n");
380            dump();
381            RELEASE_ASSERT_NOT_REACHED();
382        }
383        return value.asInt32();
384    }
385    double valueOfNumberConstant(Node* node)
386    {
387        return valueOfJSConstant(node).asNumber();
388    }
389    bool valueOfBooleanConstant(Node* node)
390    {
391        return valueOfJSConstant(node).asBoolean();
392    }
393    JSFunction* valueOfFunctionConstant(Node* node)
394    {
395        JSCell* function = getJSFunction(valueOfJSConstant(node));
396        ASSERT(function);
397        return jsCast<JSFunction*>(function);
398    }
399
400    static const char *opName(NodeType);
401
402    StructureSet* addStructureSet(const StructureSet& structureSet)
403    {
404        ASSERT(structureSet.size());
405        m_structureSet.append(structureSet);
406        return &m_structureSet.last();
407    }
408
409    StructureTransitionData* addStructureTransitionData(const StructureTransitionData& structureTransitionData)
410    {
411        m_structureTransitionData.append(structureTransitionData);
412        return &m_structureTransitionData.last();
413    }
414
415    JSGlobalObject* globalObjectFor(CodeOrigin codeOrigin)
416    {
417        return m_codeBlock->globalObjectFor(codeOrigin);
418    }
419
420    JSObject* globalThisObjectFor(CodeOrigin codeOrigin)
421    {
422        JSGlobalObject* object = globalObjectFor(codeOrigin);
423        return jsCast<JSObject*>(object->methodTable()->toThis(object, object->globalExec(), NotStrictMode));
424    }
425
426    ScriptExecutable* executableFor(InlineCallFrame* inlineCallFrame)
427    {
428        if (!inlineCallFrame)
429            return m_codeBlock->ownerExecutable();
430
431        return inlineCallFrame->executable.get();
432    }
433
434    ScriptExecutable* executableFor(const CodeOrigin& codeOrigin)
435    {
436        return executableFor(codeOrigin.inlineCallFrame);
437    }
438
439    CodeBlock* baselineCodeBlockFor(InlineCallFrame* inlineCallFrame)
440    {
441        if (!inlineCallFrame)
442            return m_profiledBlock;
443        return baselineCodeBlockForInlineCallFrame(inlineCallFrame);
444    }
445
446    CodeBlock* baselineCodeBlockFor(const CodeOrigin& codeOrigin)
447    {
448        return baselineCodeBlockForOriginAndBaselineCodeBlock(codeOrigin, m_profiledBlock);
449    }
450
451    bool isStrictModeFor(CodeOrigin codeOrigin)
452    {
453        if (!codeOrigin.inlineCallFrame)
454            return m_codeBlock->isStrictMode();
455        return jsCast<FunctionExecutable*>(codeOrigin.inlineCallFrame->executable.get())->isStrictMode();
456    }
457
458    ECMAMode ecmaModeFor(CodeOrigin codeOrigin)
459    {
460        return isStrictModeFor(codeOrigin) ? StrictMode : NotStrictMode;
461    }
462
463    bool masqueradesAsUndefinedWatchpointIsStillValid(const CodeOrigin& codeOrigin)
464    {
465        return m_plan.watchpoints.isStillValid(
466            globalObjectFor(codeOrigin)->masqueradesAsUndefinedWatchpoint());
467    }
468
469    bool hasGlobalExitSite(const CodeOrigin& codeOrigin, ExitKind exitKind)
470    {
471        return baselineCodeBlockFor(codeOrigin)->hasExitSite(FrequentExitSite(exitKind));
472    }
473
474    bool hasExitSite(const CodeOrigin& codeOrigin, ExitKind exitKind)
475    {
476        return baselineCodeBlockFor(codeOrigin)->hasExitSite(FrequentExitSite(codeOrigin.bytecodeIndex, exitKind));
477    }
478
479    bool hasExitSite(Node* node, ExitKind exitKind)
480    {
481        return hasExitSite(node->origin.semantic, exitKind);
482    }
483
484    VirtualRegister argumentsRegisterFor(InlineCallFrame* inlineCallFrame)
485    {
486        if (!inlineCallFrame)
487            return m_profiledBlock->argumentsRegister();
488
489        return VirtualRegister(baselineCodeBlockForInlineCallFrame(
490            inlineCallFrame)->argumentsRegister().offset() +
491            inlineCallFrame->stackOffset);
492    }
493
494    VirtualRegister argumentsRegisterFor(const CodeOrigin& codeOrigin)
495    {
496        return argumentsRegisterFor(codeOrigin.inlineCallFrame);
497    }
498
499    VirtualRegister machineArgumentsRegisterFor(InlineCallFrame* inlineCallFrame)
500    {
501        if (!inlineCallFrame)
502            return m_codeBlock->argumentsRegister();
503
504        return inlineCallFrame->argumentsRegister;
505    }
506
507    VirtualRegister machineArgumentsRegisterFor(const CodeOrigin& codeOrigin)
508    {
509        return machineArgumentsRegisterFor(codeOrigin.inlineCallFrame);
510    }
511
512    VirtualRegister uncheckedArgumentsRegisterFor(InlineCallFrame* inlineCallFrame)
513    {
514        if (!inlineCallFrame)
515            return m_profiledBlock->uncheckedArgumentsRegister();
516
517        CodeBlock* codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame);
518        if (!codeBlock->usesArguments())
519            return VirtualRegister();
520
521        return VirtualRegister(codeBlock->argumentsRegister().offset() +
522            inlineCallFrame->stackOffset);
523    }
524
525    VirtualRegister uncheckedArgumentsRegisterFor(const CodeOrigin& codeOrigin)
526    {
527        return uncheckedArgumentsRegisterFor(codeOrigin.inlineCallFrame);
528    }
529
530    VirtualRegister activationRegister()
531    {
532        return m_profiledBlock->activationRegister();
533    }
534
535    VirtualRegister uncheckedActivationRegister()
536    {
537        return m_profiledBlock->uncheckedActivationRegister();
538    }
539
540    VirtualRegister machineActivationRegister()
541    {
542        return m_profiledBlock->activationRegister();
543    }
544
545    VirtualRegister uncheckedMachineActivationRegister()
546    {
547        return m_profiledBlock->uncheckedActivationRegister();
548    }
549
550    ValueProfile* valueProfileFor(Node* node)
551    {
552        if (!node)
553            return 0;
554
555        CodeBlock* profiledBlock = baselineCodeBlockFor(node->origin.semantic);
556
557        if (node->op() == GetArgument)
558            return profiledBlock->valueProfileForArgument(node->local().toArgument());
559
560        if (node->hasLocal(*this)) {
561            if (m_form == SSA)
562                return 0;
563            if (!node->local().isArgument())
564                return 0;
565            int argument = node->local().toArgument();
566            if (node->variableAccessData() != m_arguments[argument]->variableAccessData())
567                return 0;
568            return profiledBlock->valueProfileForArgument(argument);
569        }
570
571        if (node->hasHeapPrediction())
572            return profiledBlock->valueProfileForBytecodeOffset(node->origin.semantic.bytecodeIndex);
573
574        return 0;
575    }
576
577    MethodOfGettingAValueProfile methodOfGettingAValueProfileFor(Node* node)
578    {
579        if (!node)
580            return MethodOfGettingAValueProfile();
581
582        CodeBlock* profiledBlock = baselineCodeBlockFor(node->origin.semantic);
583
584        if (node->op() == GetLocal) {
585            return MethodOfGettingAValueProfile::fromLazyOperand(
586                profiledBlock,
587                LazyOperandValueProfileKey(
588                    node->origin.semantic.bytecodeIndex, node->local()));
589        }
590
591        return MethodOfGettingAValueProfile(valueProfileFor(node));
592    }
593
594    bool usesArguments() const
595    {
596        return m_codeBlock->usesArguments();
597    }
598
599    BlockIndex numBlocks() const { return m_blocks.size(); }
600    BasicBlock* block(BlockIndex blockIndex) const { return m_blocks[blockIndex].get(); }
601    BasicBlock* lastBlock() const { return block(numBlocks() - 1); }
602
603    void appendBlock(PassRefPtr<BasicBlock> basicBlock)
604    {
605        basicBlock->index = m_blocks.size();
606        m_blocks.append(basicBlock);
607    }
608
609    void killBlock(BlockIndex blockIndex)
610    {
611        m_blocks[blockIndex].clear();
612    }
613
614    void killBlock(BasicBlock* basicBlock)
615    {
616        killBlock(basicBlock->index);
617    }
618
619    void killBlockAndItsContents(BasicBlock*);
620
621    void killUnreachableBlocks();
622
623    bool isPredictedNumerical(Node* node)
624    {
625        return isNumerical(node->child1().useKind()) && isNumerical(node->child2().useKind());
626    }
627
628    // Note that a 'true' return does not actually mean that the ByVal access clobbers nothing.
629    // It really means that it will not clobber the entire world. It's still up to you to
630    // carefully consider things like:
631    // - PutByVal definitely changes the array it stores to, and may even change its length.
632    // - PutByOffset definitely changes the object it stores to.
633    // - and so on.
634    bool byValIsPure(Node* node)
635    {
636        switch (node->arrayMode().type()) {
637        case Array::Generic:
638            return false;
639        case Array::Int32:
640        case Array::Double:
641        case Array::Contiguous:
642        case Array::ArrayStorage:
643            return !node->arrayMode().isOutOfBounds();
644        case Array::SlowPutArrayStorage:
645            return !node->arrayMode().mayStoreToHole();
646        case Array::String:
647            return node->op() == GetByVal && node->arrayMode().isInBounds();
648#if USE(JSVALUE32_64)
649        case Array::Arguments:
650            if (node->op() == GetByVal)
651                return true;
652            return false;
653#endif // USE(JSVALUE32_64)
654        default:
655            return true;
656        }
657    }
658
659    bool clobbersWorld(Node* node)
660    {
661        if (node->flags() & NodeClobbersWorld)
662            return true;
663        if (!(node->flags() & NodeMightClobber))
664            return false;
665        switch (node->op()) {
666        case GetByVal:
667        case PutByValDirect:
668        case PutByVal:
669        case PutByValAlias:
670            return !byValIsPure(node);
671        case ToString:
672            switch (node->child1().useKind()) {
673            case StringObjectUse:
674            case StringOrStringObjectUse:
675                return false;
676            case CellUse:
677            case UntypedUse:
678                return true;
679            default:
680                RELEASE_ASSERT_NOT_REACHED();
681                return true;
682            }
683        default:
684            RELEASE_ASSERT_NOT_REACHED();
685            return true; // If by some oddity we hit this case in release build it's safer to have CSE assume the worst.
686        }
687    }
688
689    void determineReachability();
690    void resetReachability();
691
692    void resetExitStates();
693
694    unsigned varArgNumChildren(Node* node)
695    {
696        ASSERT(node->flags() & NodeHasVarArgs);
697        return node->numChildren();
698    }
699
700    unsigned numChildren(Node* node)
701    {
702        if (node->flags() & NodeHasVarArgs)
703            return varArgNumChildren(node);
704        return AdjacencyList::Size;
705    }
706
707    Edge& varArgChild(Node* node, unsigned index)
708    {
709        ASSERT(node->flags() & NodeHasVarArgs);
710        return m_varArgChildren[node->firstChild() + index];
711    }
712
713    Edge& child(Node* node, unsigned index)
714    {
715        if (node->flags() & NodeHasVarArgs)
716            return varArgChild(node, index);
717        return node->children.child(index);
718    }
719
720    void voteNode(Node* node, unsigned ballot, float weight = 1)
721    {
722        switch (node->op()) {
723        case ValueToInt32:
724        case UInt32ToNumber:
725            node = node->child1().node();
726            break;
727        default:
728            break;
729        }
730
731        if (node->op() == GetLocal)
732            node->variableAccessData()->vote(ballot, weight);
733    }
734
735    void voteNode(Edge edge, unsigned ballot, float weight = 1)
736    {
737        voteNode(edge.node(), ballot, weight);
738    }
739
740    void voteChildren(Node* node, unsigned ballot, float weight = 1)
741    {
742        if (node->flags() & NodeHasVarArgs) {
743            for (unsigned childIdx = node->firstChild();
744                childIdx < node->firstChild() + node->numChildren();
745                childIdx++) {
746                if (!!m_varArgChildren[childIdx])
747                    voteNode(m_varArgChildren[childIdx], ballot, weight);
748            }
749            return;
750        }
751
752        if (!node->child1())
753            return;
754        voteNode(node->child1(), ballot, weight);
755        if (!node->child2())
756            return;
757        voteNode(node->child2(), ballot, weight);
758        if (!node->child3())
759            return;
760        voteNode(node->child3(), ballot, weight);
761    }
762
763    template<typename T> // T = Node* or Edge
764    void substitute(BasicBlock& block, unsigned startIndexInBlock, T oldThing, T newThing)
765    {
766        for (unsigned indexInBlock = startIndexInBlock; indexInBlock < block.size(); ++indexInBlock) {
767            Node* node = block[indexInBlock];
768            if (node->flags() & NodeHasVarArgs) {
769                for (unsigned childIdx = node->firstChild(); childIdx < node->firstChild() + node->numChildren(); ++childIdx) {
770                    if (!!m_varArgChildren[childIdx])
771                        compareAndSwap(m_varArgChildren[childIdx], oldThing, newThing);
772                }
773                continue;
774            }
775            if (!node->child1())
776                continue;
777            compareAndSwap(node->children.child1(), oldThing, newThing);
778            if (!node->child2())
779                continue;
780            compareAndSwap(node->children.child2(), oldThing, newThing);
781            if (!node->child3())
782                continue;
783            compareAndSwap(node->children.child3(), oldThing, newThing);
784        }
785    }
786
787    // Use this if you introduce a new GetLocal and you know that you introduced it *before*
788    // any GetLocals in the basic block.
789    // FIXME: it may be appropriate, in the future, to generalize this to handle GetLocals
790    // introduced anywhere in the basic block.
791    void substituteGetLocal(BasicBlock& block, unsigned startIndexInBlock, VariableAccessData* variableAccessData, Node* newGetLocal);
792
793    void invalidateCFG();
794
795    void clearFlagsOnAllNodes(NodeFlags);
796
797    void clearReplacements();
798    void initializeNodeOwners();
799
800    void getBlocksInDepthFirstOrder(Vector<BasicBlock*>& result);
801
802    Profiler::Compilation* compilation() { return m_plan.compilation.get(); }
803
804    DesiredIdentifiers& identifiers() { return m_plan.identifiers; }
805    DesiredWatchpoints& watchpoints() { return m_plan.watchpoints; }
806    DesiredStructureChains& chains() { return m_plan.chains; }
807
808    FullBytecodeLiveness& livenessFor(CodeBlock*);
809    FullBytecodeLiveness& livenessFor(InlineCallFrame*);
810    bool isLiveInBytecode(VirtualRegister, CodeOrigin);
811
812    unsigned frameRegisterCount();
813    unsigned stackPointerOffset();
814    unsigned requiredRegisterCountForExit();
815    unsigned requiredRegisterCountForExecutionAndExit();
816
817    JSActivation* tryGetActivation(Node*);
818    WriteBarrierBase<Unknown>* tryGetRegisters(Node*);
819
820    JSArrayBufferView* tryGetFoldableView(Node*);
821    JSArrayBufferView* tryGetFoldableView(Node*, ArrayMode);
822    JSArrayBufferView* tryGetFoldableViewForChild1(Node*);
823
824    virtual void visitChildren(SlotVisitor&) override;
825
826    VM& m_vm;
827    Plan& m_plan;
828    CodeBlock* m_codeBlock;
829    CodeBlock* m_profiledBlock;
830
831    NodeAllocator& m_allocator;
832
833    Operands<AbstractValue> m_mustHandleAbstractValues;
834
835    Vector< RefPtr<BasicBlock> , 8> m_blocks;
836    Vector<Edge, 16> m_varArgChildren;
837    Vector<StorageAccessData> m_storageAccessData;
838    Vector<Node*, 8> m_arguments;
839    SegmentedVector<VariableAccessData, 16> m_variableAccessData;
840    SegmentedVector<ArgumentPosition, 8> m_argumentPositions;
841    SegmentedVector<StructureSet, 16> m_structureSet;
842    SegmentedVector<StructureTransitionData, 8> m_structureTransitionData;
843    SegmentedVector<NewArrayBufferData, 4> m_newArrayBufferData;
844    Bag<BranchData> m_branchData;
845    Bag<SwitchData> m_switchData;
846    Bag<MultiGetByOffsetData> m_multiGetByOffsetData;
847    Bag<MultiPutByOffsetData> m_multiPutByOffsetData;
848    Vector<InlineVariableData, 4> m_inlineVariableData;
849    HashMap<CodeBlock*, std::unique_ptr<FullBytecodeLiveness>> m_bytecodeLiveness;
850    bool m_hasArguments;
851    HashSet<ExecutableBase*> m_executablesWhoseArgumentsEscaped;
852    BitVector m_lazyVars;
853    Dominators m_dominators;
854    NaturalLoops m_naturalLoops;
855    unsigned m_localVars;
856    unsigned m_nextMachineLocal;
857    unsigned m_parameterSlots;
858    int m_machineCaptureStart;
859    std::unique_ptr<SlowArgument[]> m_slowArguments;
860
861#if USE(JSVALUE32_64)
862    std::unordered_map<int64_t, double*> m_doubleConstantsMap;
863    std::unique_ptr<Bag<double>> m_doubleConstants;
864#endif
865
866    OptimizationFixpointState m_fixpointState;
867    GraphForm m_form;
868    UnificationState m_unificationState;
869    RefCountState m_refCountState;
870private:
871
872    void handleSuccessor(Vector<BasicBlock*, 16>& worklist, BasicBlock*, BasicBlock* successor);
873    void addForDepthFirstSort(Vector<BasicBlock*>& result, Vector<BasicBlock*, 16>& worklist, HashSet<BasicBlock*>& seen, BasicBlock*);
874
875    AddSpeculationMode addImmediateShouldSpeculateInt32(Node* add, bool variableShouldSpeculateInt32, Node* immediate, RareCaseProfilingSource source)
876    {
877        ASSERT(immediate->hasConstant());
878
879        JSValue immediateValue = immediate->valueOfJSConstant(m_codeBlock);
880        if (!immediateValue.isNumber() && !immediateValue.isBoolean())
881            return DontSpeculateInt32;
882
883        if (!variableShouldSpeculateInt32)
884            return DontSpeculateInt32;
885
886        if (immediateValue.isInt32() || immediateValue.isBoolean())
887            return add->canSpeculateInt32(source) ? SpeculateInt32 : DontSpeculateInt32;
888
889        double doubleImmediate = immediateValue.asDouble();
890        const double twoToThe48 = 281474976710656.0;
891        if (doubleImmediate < -twoToThe48 || doubleImmediate > twoToThe48)
892            return DontSpeculateInt32;
893
894        return bytecodeCanTruncateInteger(add->arithNodeFlags()) ? SpeculateInt32AndTruncateConstants : DontSpeculateInt32;
895    }
896};
897
898#define DFG_NODE_DO_TO_CHILDREN(graph, node, thingToDo) do {            \
899        Node* _node = (node);                                           \
900        if (_node->flags() & NodeHasVarArgs) {                          \
901            for (unsigned _childIdx = _node->firstChild();              \
902                _childIdx < _node->firstChild() + _node->numChildren(); \
903                _childIdx++) {                                          \
904                if (!!(graph).m_varArgChildren[_childIdx])              \
905                    thingToDo(_node, (graph).m_varArgChildren[_childIdx]); \
906            }                                                           \
907        } else {                                                        \
908            if (!_node->child1()) {                                     \
909                ASSERT(                                                 \
910                    !_node->child2()                                    \
911                    && !_node->child3());                               \
912                break;                                                  \
913            }                                                           \
914            thingToDo(_node, _node->child1());                          \
915                                                                        \
916            if (!_node->child2()) {                                     \
917                ASSERT(!_node->child3());                               \
918                break;                                                  \
919            }                                                           \
920            thingToDo(_node, _node->child2());                          \
921                                                                        \
922            if (!_node->child3())                                       \
923                break;                                                  \
924            thingToDo(_node, _node->child3());                          \
925        }                                                               \
926    } while (false)
927
928} } // namespace JSC::DFG
929
930#endif
931#endif
932