c6ad4958da2ae0f6762ce3cd46c9ae7155dc7f74
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGGraph.h
1 /*
2  * Copyright (C) 2011-2015 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 "BytecodeLivenessAnalysisInlines.h"
33 #include "CodeBlock.h"
34 #include "DFGArgumentPosition.h"
35 #include "DFGBasicBlock.h"
36 #include "DFGDominators.h"
37 #include "DFGFrozenValue.h"
38 #include "DFGLongLivedState.h"
39 #include "DFGNaturalLoops.h"
40 #include "DFGNode.h"
41 #include "DFGNodeAllocator.h"
42 #include "DFGPlan.h"
43 #include "DFGPrePostNumbering.h"
44 #include "DFGScannable.h"
45 #include "FullBytecodeLiveness.h"
46 #include "JSStack.h"
47 #include "MethodOfGettingAValueProfile.h"
48 #include <unordered_map>
49 #include <wtf/BitVector.h>
50 #include <wtf/HashMap.h>
51 #include <wtf/Vector.h>
52 #include <wtf/StdLibExtras.h>
53
54 namespace JSC {
55
56 class CodeBlock;
57 class ExecState;
58
59 namespace DFG {
60
61 #define DFG_NODE_DO_TO_CHILDREN(graph, node, thingToDo) do {            \
62         Node* _node = (node);                                           \
63         if (_node->flags() & NodeHasVarArgs) {                          \
64             for (unsigned _childIdx = _node->firstChild();              \
65                 _childIdx < _node->firstChild() + _node->numChildren(); \
66                 _childIdx++) {                                          \
67                 if (!!(graph).m_varArgChildren[_childIdx])              \
68                     thingToDo(_node, (graph).m_varArgChildren[_childIdx]); \
69             }                                                           \
70         } else {                                                        \
71             if (!_node->child1()) {                                     \
72                 ASSERT(                                                 \
73                     !_node->child2()                                    \
74                     && !_node->child3());                               \
75                 break;                                                  \
76             }                                                           \
77             thingToDo(_node, _node->child1());                          \
78                                                                         \
79             if (!_node->child2()) {                                     \
80                 ASSERT(!_node->child3());                               \
81                 break;                                                  \
82             }                                                           \
83             thingToDo(_node, _node->child2());                          \
84                                                                         \
85             if (!_node->child3())                                       \
86                 break;                                                  \
87             thingToDo(_node, _node->child3());                          \
88         }                                                               \
89     } while (false)
90
91 #define DFG_ASSERT(graph, node, assertion) do {                         \
92         if (!!(assertion))                                              \
93             break;                                                      \
94         (graph).handleAssertionFailure(                                 \
95             (node), __FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion); \
96     } while (false)
97
98 #define DFG_CRASH(graph, node, reason) do {                             \
99         (graph).handleAssertionFailure(                                 \
100             (node), __FILE__, __LINE__, WTF_PRETTY_FUNCTION, (reason)); \
101     } while (false)
102
103 struct InlineVariableData {
104     InlineCallFrame* inlineCallFrame;
105     unsigned argumentPositionStart;
106     VariableAccessData* calleeVariable;
107 };
108
109 enum AddSpeculationMode {
110     DontSpeculateInt32,
111     SpeculateInt32AndTruncateConstants,
112     SpeculateInt32
113 };
114
115 //
116 // === Graph ===
117 //
118 // The order may be significant for nodes with side-effects (property accesses, value conversions).
119 // Nodes that are 'dead' remain in the vector with refCount 0.
120 class Graph : public virtual Scannable {
121 public:
122     Graph(VM&, Plan&, LongLivedState&);
123     ~Graph();
124     
125     void changeChild(Edge& edge, Node* newNode)
126     {
127         edge.setNode(newNode);
128     }
129     
130     void changeEdge(Edge& edge, Edge newEdge)
131     {
132         edge = newEdge;
133     }
134     
135     void compareAndSwap(Edge& edge, Node* oldNode, Node* newNode)
136     {
137         if (edge.node() != oldNode)
138             return;
139         changeChild(edge, newNode);
140     }
141     
142     void compareAndSwap(Edge& edge, Edge oldEdge, Edge newEdge)
143     {
144         if (edge != oldEdge)
145             return;
146         changeEdge(edge, newEdge);
147     }
148     
149     void performSubstitution(Node* node)
150     {
151         if (node->flags() & NodeHasVarArgs) {
152             for (unsigned childIdx = node->firstChild(); childIdx < node->firstChild() + node->numChildren(); childIdx++)
153                 performSubstitutionForEdge(m_varArgChildren[childIdx]);
154         } else {
155             performSubstitutionForEdge(node->child1());
156             performSubstitutionForEdge(node->child2());
157             performSubstitutionForEdge(node->child3());
158         }
159     }
160     
161     void performSubstitutionForEdge(Edge& child)
162     {
163         // Check if this operand is actually unused.
164         if (!child)
165             return;
166         
167         // Check if there is any replacement.
168         Node* replacement = child->replacement();
169         if (!replacement)
170             return;
171         
172         child.setNode(replacement);
173         
174         // There is definitely a replacement. Assert that the replacement does not
175         // have a replacement.
176         ASSERT(!child->replacement());
177     }
178     
179     template<typename... Params>
180     Node* addNode(SpeculatedType type, Params... params)
181     {
182         Node* node = new (m_allocator) Node(params...);
183         node->predict(type);
184         return node;
185     }
186
187     void dethread();
188     
189     FrozenValue* freeze(JSValue); // We use weak freezing by default.
190     FrozenValue* freezeStrong(JSValue); // Shorthand for freeze(value)->strengthenTo(StrongValue).
191     
192     void convertToConstant(Node* node, FrozenValue* value);
193     void convertToConstant(Node* node, JSValue value);
194     void convertToStrongConstant(Node* node, JSValue value);
195     
196     StructureRegistrationResult registerStructure(Structure* structure);
197     void assertIsRegistered(Structure* structure);
198     
199     // CodeBlock is optional, but may allow additional information to be dumped (e.g. Identifier names).
200     void dump(PrintStream& = WTF::dataFile(), DumpContext* = 0);
201     
202     bool terminalsAreValid();
203     
204     enum PhiNodeDumpMode { DumpLivePhisOnly, DumpAllPhis };
205     void dumpBlockHeader(PrintStream&, const char* prefix, BasicBlock*, PhiNodeDumpMode, DumpContext*);
206     void dump(PrintStream&, Edge);
207     void dump(PrintStream&, const char* prefix, Node*, DumpContext* = 0);
208     static int amountOfNodeWhiteSpace(Node*);
209     static void printNodeWhiteSpace(PrintStream&, Node*);
210
211     // Dump the code origin of the given node as a diff from the code origin of the
212     // preceding node. Returns true if anything was printed.
213     bool dumpCodeOrigin(PrintStream&, const char* prefix, Node* previousNode, Node* currentNode, DumpContext*);
214
215     AddSpeculationMode addSpeculationMode(Node* add, bool leftShouldSpeculateInt32, bool rightShouldSpeculateInt32, PredictionPass pass)
216     {
217         ASSERT(add->op() == ValueAdd || add->op() == ArithAdd || add->op() == ArithSub);
218         
219         RareCaseProfilingSource source = add->sourceFor(pass);
220         
221         Node* left = add->child1().node();
222         Node* right = add->child2().node();
223         
224         if (left->hasConstant())
225             return addImmediateShouldSpeculateInt32(add, rightShouldSpeculateInt32, right, left, source);
226         if (right->hasConstant())
227             return addImmediateShouldSpeculateInt32(add, leftShouldSpeculateInt32, left, right, source);
228         
229         return (leftShouldSpeculateInt32 && rightShouldSpeculateInt32 && add->canSpeculateInt32(source)) ? SpeculateInt32 : DontSpeculateInt32;
230     }
231     
232     AddSpeculationMode valueAddSpeculationMode(Node* add, PredictionPass pass)
233     {
234         return addSpeculationMode(
235             add,
236             add->child1()->shouldSpeculateInt32OrBooleanExpectingDefined(),
237             add->child2()->shouldSpeculateInt32OrBooleanExpectingDefined(),
238             pass);
239     }
240     
241     AddSpeculationMode arithAddSpeculationMode(Node* add, PredictionPass pass)
242     {
243         return addSpeculationMode(
244             add,
245             add->child1()->shouldSpeculateInt32OrBooleanForArithmetic(),
246             add->child2()->shouldSpeculateInt32OrBooleanForArithmetic(),
247             pass);
248     }
249     
250     AddSpeculationMode addSpeculationMode(Node* add, PredictionPass pass)
251     {
252         if (add->op() == ValueAdd)
253             return valueAddSpeculationMode(add, pass);
254         
255         return arithAddSpeculationMode(add, pass);
256     }
257     
258     bool addShouldSpeculateInt32(Node* add, PredictionPass pass)
259     {
260         return addSpeculationMode(add, pass) != DontSpeculateInt32;
261     }
262     
263     bool addShouldSpeculateMachineInt(Node* add)
264     {
265         if (!enableInt52())
266             return false;
267         
268         Node* left = add->child1().node();
269         Node* right = add->child2().node();
270
271         bool speculation = Node::shouldSpeculateMachineInt(left, right);
272         return speculation && !hasExitSite(add, Int52Overflow);
273     }
274     
275     bool mulShouldSpeculateInt32(Node* mul, PredictionPass pass)
276     {
277         ASSERT(mul->op() == ArithMul);
278         
279         Node* left = mul->child1().node();
280         Node* right = mul->child2().node();
281         
282         return Node::shouldSpeculateInt32OrBooleanForArithmetic(left, right)
283             && mul->canSpeculateInt32(mul->sourceFor(pass));
284     }
285     
286     bool mulShouldSpeculateMachineInt(Node* mul, PredictionPass pass)
287     {
288         ASSERT(mul->op() == ArithMul);
289         
290         if (!enableInt52())
291             return false;
292         
293         Node* left = mul->child1().node();
294         Node* right = mul->child2().node();
295
296         return Node::shouldSpeculateMachineInt(left, right)
297             && mul->canSpeculateInt52(pass)
298             && !hasExitSite(mul, Int52Overflow);
299     }
300     
301     bool negateShouldSpeculateInt32(Node* negate, PredictionPass pass)
302     {
303         ASSERT(negate->op() == ArithNegate);
304         return negate->child1()->shouldSpeculateInt32OrBooleanForArithmetic()
305             && negate->canSpeculateInt32(pass);
306     }
307     
308     bool negateShouldSpeculateMachineInt(Node* negate, PredictionPass pass)
309     {
310         ASSERT(negate->op() == ArithNegate);
311         if (!enableInt52())
312             return false;
313         return negate->child1()->shouldSpeculateMachineInt()
314             && !hasExitSite(negate, Int52Overflow)
315             && negate->canSpeculateInt52(pass);
316     }
317
318     bool roundShouldSpeculateInt32(Node* arithRound, PredictionPass pass)
319     {
320         ASSERT(arithRound->op() == ArithRound);
321         return arithRound->canSpeculateInt32(pass) && !hasExitSite(arithRound->origin.semantic, Overflow) && !hasExitSite(arithRound->origin.semantic, NegativeZero);
322     }
323     
324     static const char *opName(NodeType);
325     
326     StructureSet* addStructureSet(const StructureSet& structureSet)
327     {
328         m_structureSet.append(structureSet);
329         return &m_structureSet.last();
330     }
331     
332     JSGlobalObject* globalObjectFor(CodeOrigin codeOrigin)
333     {
334         return m_codeBlock->globalObjectFor(codeOrigin);
335     }
336     
337     JSObject* globalThisObjectFor(CodeOrigin codeOrigin)
338     {
339         JSGlobalObject* object = globalObjectFor(codeOrigin);
340         return jsCast<JSObject*>(object->methodTable()->toThis(object, object->globalExec(), NotStrictMode));
341     }
342     
343     ScriptExecutable* executableFor(InlineCallFrame* inlineCallFrame)
344     {
345         if (!inlineCallFrame)
346             return m_codeBlock->ownerExecutable();
347         
348         return inlineCallFrame->executable.get();
349     }
350     
351     ScriptExecutable* executableFor(const CodeOrigin& codeOrigin)
352     {
353         return executableFor(codeOrigin.inlineCallFrame);
354     }
355     
356     CodeBlock* baselineCodeBlockFor(InlineCallFrame* inlineCallFrame)
357     {
358         if (!inlineCallFrame)
359             return m_profiledBlock;
360         return baselineCodeBlockForInlineCallFrame(inlineCallFrame);
361     }
362     
363     CodeBlock* baselineCodeBlockFor(const CodeOrigin& codeOrigin)
364     {
365         return baselineCodeBlockForOriginAndBaselineCodeBlock(codeOrigin, m_profiledBlock);
366     }
367     
368     bool isStrictModeFor(CodeOrigin codeOrigin)
369     {
370         if (!codeOrigin.inlineCallFrame)
371             return m_codeBlock->isStrictMode();
372         return jsCast<FunctionExecutable*>(codeOrigin.inlineCallFrame->executable.get())->isStrictMode();
373     }
374     
375     ECMAMode ecmaModeFor(CodeOrigin codeOrigin)
376     {
377         return isStrictModeFor(codeOrigin) ? StrictMode : NotStrictMode;
378     }
379     
380     bool masqueradesAsUndefinedWatchpointIsStillValid(const CodeOrigin& codeOrigin)
381     {
382         return globalObjectFor(codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid();
383     }
384     
385     bool hasGlobalExitSite(const CodeOrigin& codeOrigin, ExitKind exitKind)
386     {
387         return baselineCodeBlockFor(codeOrigin)->hasExitSite(FrequentExitSite(exitKind));
388     }
389     
390     bool hasExitSite(const CodeOrigin& codeOrigin, ExitKind exitKind)
391     {
392         return baselineCodeBlockFor(codeOrigin)->hasExitSite(FrequentExitSite(codeOrigin.bytecodeIndex, exitKind));
393     }
394     
395     bool hasExitSite(Node* node, ExitKind exitKind)
396     {
397         return hasExitSite(node->origin.semantic, exitKind);
398     }
399     
400     VirtualRegister activationRegister()
401     {
402         return m_profiledBlock->activationRegister();
403     }
404     
405     VirtualRegister uncheckedActivationRegister()
406     {
407         return m_profiledBlock->uncheckedActivationRegister();
408     }
409     
410     VirtualRegister machineActivationRegister()
411     {
412         return m_profiledBlock->activationRegister();
413     }
414     
415     VirtualRegister uncheckedMachineActivationRegister()
416     {
417         return m_profiledBlock->uncheckedActivationRegister();
418     }
419     
420     ValueProfile* valueProfileFor(Node*);
421     MethodOfGettingAValueProfile methodOfGettingAValueProfileFor(Node*);
422     
423     BlockIndex numBlocks() const { return m_blocks.size(); }
424     BasicBlock* block(BlockIndex blockIndex) const { return m_blocks[blockIndex].get(); }
425     BasicBlock* lastBlock() const { return block(numBlocks() - 1); }
426
427     void appendBlock(PassRefPtr<BasicBlock> basicBlock)
428     {
429         basicBlock->index = m_blocks.size();
430         m_blocks.append(basicBlock);
431     }
432     
433     void killBlock(BlockIndex blockIndex)
434     {
435         m_blocks[blockIndex] = nullptr;
436     }
437     
438     void killBlock(BasicBlock* basicBlock)
439     {
440         killBlock(basicBlock->index);
441     }
442     
443     void killBlockAndItsContents(BasicBlock*);
444     
445     void killUnreachableBlocks();
446     
447     void determineReachability();
448     void resetReachability();
449     
450     void computeRefCounts();
451     
452     unsigned varArgNumChildren(Node* node)
453     {
454         ASSERT(node->flags() & NodeHasVarArgs);
455         return node->numChildren();
456     }
457     
458     unsigned numChildren(Node* node)
459     {
460         if (node->flags() & NodeHasVarArgs)
461             return varArgNumChildren(node);
462         return AdjacencyList::Size;
463     }
464     
465     Edge& varArgChild(Node* node, unsigned index)
466     {
467         ASSERT(node->flags() & NodeHasVarArgs);
468         return m_varArgChildren[node->firstChild() + index];
469     }
470     
471     Edge& child(Node* node, unsigned index)
472     {
473         if (node->flags() & NodeHasVarArgs)
474             return varArgChild(node, index);
475         return node->children.child(index);
476     }
477     
478     void voteNode(Node* node, unsigned ballot, float weight = 1)
479     {
480         switch (node->op()) {
481         case ValueToInt32:
482         case UInt32ToNumber:
483             node = node->child1().node();
484             break;
485         default:
486             break;
487         }
488         
489         if (node->op() == GetLocal)
490             node->variableAccessData()->vote(ballot, weight);
491     }
492     
493     void voteNode(Edge edge, unsigned ballot, float weight = 1)
494     {
495         voteNode(edge.node(), ballot, weight);
496     }
497     
498     void voteChildren(Node* node, unsigned ballot, float weight = 1)
499     {
500         if (node->flags() & NodeHasVarArgs) {
501             for (unsigned childIdx = node->firstChild();
502                 childIdx < node->firstChild() + node->numChildren();
503                 childIdx++) {
504                 if (!!m_varArgChildren[childIdx])
505                     voteNode(m_varArgChildren[childIdx], ballot, weight);
506             }
507             return;
508         }
509         
510         if (!node->child1())
511             return;
512         voteNode(node->child1(), ballot, weight);
513         if (!node->child2())
514             return;
515         voteNode(node->child2(), ballot, weight);
516         if (!node->child3())
517             return;
518         voteNode(node->child3(), ballot, weight);
519     }
520     
521     template<typename T> // T = Node* or Edge
522     void substitute(BasicBlock& block, unsigned startIndexInBlock, T oldThing, T newThing)
523     {
524         for (unsigned indexInBlock = startIndexInBlock; indexInBlock < block.size(); ++indexInBlock) {
525             Node* node = block[indexInBlock];
526             if (node->flags() & NodeHasVarArgs) {
527                 for (unsigned childIdx = node->firstChild(); childIdx < node->firstChild() + node->numChildren(); ++childIdx) {
528                     if (!!m_varArgChildren[childIdx])
529                         compareAndSwap(m_varArgChildren[childIdx], oldThing, newThing);
530                 }
531                 continue;
532             }
533             if (!node->child1())
534                 continue;
535             compareAndSwap(node->children.child1(), oldThing, newThing);
536             if (!node->child2())
537                 continue;
538             compareAndSwap(node->children.child2(), oldThing, newThing);
539             if (!node->child3())
540                 continue;
541             compareAndSwap(node->children.child3(), oldThing, newThing);
542         }
543     }
544     
545     // Use this if you introduce a new GetLocal and you know that you introduced it *before*
546     // any GetLocals in the basic block.
547     // FIXME: it may be appropriate, in the future, to generalize this to handle GetLocals
548     // introduced anywhere in the basic block.
549     void substituteGetLocal(BasicBlock& block, unsigned startIndexInBlock, VariableAccessData* variableAccessData, Node* newGetLocal);
550     
551     void invalidateCFG();
552     
553     void clearFlagsOnAllNodes(NodeFlags);
554     
555     void clearReplacements();
556     void clearEpochs();
557     void initializeNodeOwners();
558     
559     BlockList blocksInPreOrder();
560     BlockList blocksInPostOrder();
561     
562     class NaturalBlockIterable {
563     public:
564         NaturalBlockIterable()
565             : m_graph(nullptr)
566         {
567         }
568         
569         NaturalBlockIterable(Graph& graph)
570             : m_graph(&graph)
571         {
572         }
573         
574         class iterator {
575         public:
576             iterator()
577                 : m_graph(nullptr)
578                 , m_index(0)
579             {
580             }
581             
582             iterator(Graph& graph, BlockIndex index)
583                 : m_graph(&graph)
584                 , m_index(findNext(index))
585             {
586             }
587             
588             BasicBlock *operator*()
589             {
590                 return m_graph->block(m_index);
591             }
592             
593             iterator& operator++()
594             {
595                 m_index = findNext(m_index + 1);
596                 return *this;
597             }
598             
599             bool operator==(const iterator& other) const
600             {
601                 return m_index == other.m_index;
602             }
603             
604             bool operator!=(const iterator& other) const
605             {
606                 return !(*this == other);
607             }
608             
609         private:
610             BlockIndex findNext(BlockIndex index)
611             {
612                 while (index < m_graph->numBlocks() && !m_graph->block(index))
613                     index++;
614                 return index;
615             }
616             
617             Graph* m_graph;
618             BlockIndex m_index;
619         };
620         
621         iterator begin()
622         {
623             return iterator(*m_graph, 0);
624         }
625         
626         iterator end()
627         {
628             return iterator(*m_graph, m_graph->numBlocks());
629         }
630         
631     private:
632         Graph* m_graph;
633     };
634     
635     NaturalBlockIterable blocksInNaturalOrder()
636     {
637         return NaturalBlockIterable(*this);
638     }
639     
640     template<typename ChildFunctor>
641     void doToChildrenWithNode(Node* node, const ChildFunctor& functor)
642     {
643         DFG_NODE_DO_TO_CHILDREN(*this, node, functor);
644     }
645     
646     template<typename ChildFunctor>
647     void doToChildren(Node* node, const ChildFunctor& functor)
648     {
649         doToChildrenWithNode(
650             node,
651             [&functor] (Node*, Edge& edge) {
652                 functor(edge);
653             });
654     }
655     
656     bool uses(Node* node, Node* child)
657     {
658         bool result = false;
659         doToChildren(node, [&] (Edge edge) { result |= edge == child; });
660         return result;
661     }
662     
663     Profiler::Compilation* compilation() { return m_plan.compilation.get(); }
664     
665     DesiredIdentifiers& identifiers() { return m_plan.identifiers; }
666     DesiredWatchpoints& watchpoints() { return m_plan.watchpoints; }
667     
668     FullBytecodeLiveness& livenessFor(CodeBlock*);
669     FullBytecodeLiveness& livenessFor(InlineCallFrame*);
670     
671     // Quickly query if a single local is live at the given point. This is faster than calling
672     // forAllLiveInBytecode() if you will only query one local. But, if you want to know all of the
673     // locals live, then calling this for each local is much slower than forAllLiveInBytecode().
674     bool isLiveInBytecode(VirtualRegister, CodeOrigin);
675     
676     // Quickly get all of the non-argument locals live at the given point. This doesn't give you
677     // any arguments because those are all presumed live. You can call forAllLiveInBytecode() to
678     // also get the arguments. This is much faster than calling isLiveInBytecode() for each local.
679     template<typename Functor>
680     void forAllLocalsLiveInBytecode(CodeOrigin codeOrigin, const Functor& functor)
681     {
682         // Support for not redundantly reporting arguments. Necessary because in case of a varargs
683         // call, only the callee knows that arguments are live while in the case of a non-varargs
684         // call, both callee and caller will see the variables live.
685         VirtualRegister exclusionStart;
686         VirtualRegister exclusionEnd;
687         
688         for (;;) {
689             InlineCallFrame* inlineCallFrame = codeOrigin.inlineCallFrame;
690             VirtualRegister stackOffset(inlineCallFrame ? inlineCallFrame->stackOffset : 0);
691             
692             if (inlineCallFrame) {
693                 if (inlineCallFrame->isClosureCall)
694                     functor(stackOffset + JSStack::Callee);
695                 if (inlineCallFrame->isVarargs())
696                     functor(stackOffset + JSStack::ArgumentCount);
697             }
698             
699             CodeBlock* codeBlock = baselineCodeBlockFor(inlineCallFrame);
700             FullBytecodeLiveness& fullLiveness = livenessFor(codeBlock);
701             const FastBitVector& liveness = fullLiveness.getLiveness(codeOrigin.bytecodeIndex);
702             for (unsigned relativeLocal = codeBlock->m_numCalleeRegisters; relativeLocal--;) {
703                 VirtualRegister reg = stackOffset + virtualRegisterForLocal(relativeLocal);
704                 
705                 // Don't report if our callee already reported.
706                 if (reg >= exclusionStart && reg < exclusionEnd)
707                     continue;
708                 
709                 if (liveness.get(relativeLocal))
710                     functor(reg);
711             }
712             
713             if (!inlineCallFrame)
714                 break;
715
716             // Arguments are always live. This would be redundant if it wasn't for our
717             // op_call_varargs inlining. See the comment above.
718             exclusionStart = stackOffset + CallFrame::argumentOffsetIncludingThis(0);
719             exclusionEnd = stackOffset + CallFrame::argumentOffsetIncludingThis(inlineCallFrame->arguments.size());
720             
721             // We will always have a "this" argument and exclusionStart should be a smaller stack
722             // offset than exclusionEnd.
723             ASSERT(exclusionStart < exclusionEnd);
724
725             for (VirtualRegister reg = exclusionStart; reg < exclusionEnd; reg += 1)
726                 functor(reg);
727             
728             codeOrigin = inlineCallFrame->caller;
729         }
730     }
731     
732     // Get a BitVector of all of the non-argument locals live right now. This is mostly useful if
733     // you want to compare two sets of live locals from two different CodeOrigins.
734     BitVector localsLiveInBytecode(CodeOrigin);
735     
736     // Tells you all of the arguments and locals live at the given CodeOrigin. This is a small
737     // extension to forAllLocalsLiveInBytecode(), since all arguments are always presumed live.
738     template<typename Functor>
739     void forAllLiveInBytecode(CodeOrigin codeOrigin, const Functor& functor)
740     {
741         forAllLocalsLiveInBytecode(codeOrigin, functor);
742         
743         // Report all arguments as being live.
744         for (unsigned argument = block(0)->variablesAtHead.numberOfArguments(); argument--;)
745             functor(virtualRegisterForArgument(argument));
746     }
747     
748     BytecodeKills& killsFor(CodeBlock*);
749     BytecodeKills& killsFor(InlineCallFrame*);
750     
751     unsigned frameRegisterCount();
752     unsigned stackPointerOffset();
753     unsigned requiredRegisterCountForExit();
754     unsigned requiredRegisterCountForExecutionAndExit();
755     
756     JSValue tryGetConstantProperty(JSValue base, const StructureSet&, PropertyOffset);
757     JSValue tryGetConstantProperty(JSValue base, Structure*, PropertyOffset);
758     JSValue tryGetConstantProperty(JSValue base, const StructureAbstractValue&, PropertyOffset);
759     JSValue tryGetConstantProperty(const AbstractValue&, PropertyOffset);
760     
761     JSValue tryGetConstantClosureVar(JSValue base, ScopeOffset);
762     JSValue tryGetConstantClosureVar(const AbstractValue&, ScopeOffset);
763     JSValue tryGetConstantClosureVar(Node*, ScopeOffset);
764     
765     JSArrayBufferView* tryGetFoldableView(JSValue);
766     JSArrayBufferView* tryGetFoldableView(JSValue, ArrayMode arrayMode);
767     
768     void registerFrozenValues();
769     
770     virtual void visitChildren(SlotVisitor&) override;
771     
772     NO_RETURN_DUE_TO_CRASH void handleAssertionFailure(
773         std::nullptr_t, const char* file, int line, const char* function,
774         const char* assertion);
775     NO_RETURN_DUE_TO_CRASH void handleAssertionFailure(
776         Node*, const char* file, int line, const char* function,
777         const char* assertion);
778     NO_RETURN_DUE_TO_CRASH void handleAssertionFailure(
779         BasicBlock*, const char* file, int line, const char* function,
780         const char* assertion);
781
782     bool hasDebuggerEnabled() const { return m_hasDebuggerEnabled; }
783
784     VM& m_vm;
785     Plan& m_plan;
786     CodeBlock* m_codeBlock;
787     CodeBlock* m_profiledBlock;
788     
789     NodeAllocator& m_allocator;
790
791     Vector< RefPtr<BasicBlock> , 8> m_blocks;
792     Vector<Edge, 16> m_varArgChildren;
793
794     HashMap<EncodedJSValue, FrozenValue*, EncodedJSValueHash, EncodedJSValueHashTraits> m_frozenValueMap;
795     Bag<FrozenValue> m_frozenValues;
796
797     Vector<uint32_t> m_uint32ValuesInUse;
798     
799     Bag<StorageAccessData> m_storageAccessData;
800     
801     // In CPS, this is all of the SetArgument nodes for the arguments in the machine code block
802     // that survived DCE. All of them except maybe "this" will survive DCE, because of the Flush
803     // nodes.
804     //
805     // In SSA, this is all of the GetStack nodes for the arguments in the machine code block that
806     // may have some speculation in the prologue and survived DCE. Note that to get the speculation
807     // for an argument in SSA, you must use m_argumentFormats, since we still have to speculate
808     // even if the argument got killed. For example:
809     //
810     //     function foo(x) {
811     //        var tmp = x + 1;
812     //     }
813     //
814     // Assume that x is always int during profiling. The ArithAdd for "x + 1" will be dead and will
815     // have a proven check for the edge to "x". So, we will not insert a Check node and we will
816     // kill the GetStack for "x". But, we must do the int check in the progolue, because that's the
817     // thing we used to allow DCE of ArithAdd. Otherwise the add could be impure:
818     //
819     //     var o = {
820     //         valueOf: function() { do side effects; }
821     //     };
822     //     foo(o);
823     //
824     // If we DCE the ArithAdd and we remove the int check on x, then this won't do the side
825     // effects.
826     Vector<Node*, 8> m_arguments;
827     
828     // In CPS, this is meaningless. In SSA, this is the argument speculation that we've locked in.
829     Vector<FlushFormat> m_argumentFormats;
830     
831     SegmentedVector<VariableAccessData, 16> m_variableAccessData;
832     SegmentedVector<ArgumentPosition, 8> m_argumentPositions;
833     SegmentedVector<StructureSet, 16> m_structureSet;
834     Bag<Transition> m_transitions;
835     SegmentedVector<NewArrayBufferData, 4> m_newArrayBufferData;
836     Bag<BranchData> m_branchData;
837     Bag<SwitchData> m_switchData;
838     Bag<MultiGetByOffsetData> m_multiGetByOffsetData;
839     Bag<MultiPutByOffsetData> m_multiPutByOffsetData;
840     Bag<ObjectMaterializationData> m_objectMaterializationData;
841     Bag<CallVarargsData> m_callVarargsData;
842     Bag<LoadVarargsData> m_loadVarargsData;
843     Bag<StackAccessData> m_stackAccessData;
844     Vector<InlineVariableData, 4> m_inlineVariableData;
845     HashMap<CodeBlock*, std::unique_ptr<FullBytecodeLiveness>> m_bytecodeLiveness;
846     HashMap<CodeBlock*, std::unique_ptr<BytecodeKills>> m_bytecodeKills;
847     Dominators m_dominators;
848     PrePostNumbering m_prePostNumbering;
849     NaturalLoops m_naturalLoops;
850     unsigned m_localVars;
851     unsigned m_nextMachineLocal;
852     unsigned m_parameterSlots;
853
854 #if USE(JSVALUE32_64)
855     std::unordered_map<int64_t, double*> m_doubleConstantsMap;
856     std::unique_ptr<Bag<double>> m_doubleConstants;
857 #endif
858     
859     OptimizationFixpointState m_fixpointState;
860     StructureRegistrationState m_structureRegistrationState;
861     GraphForm m_form;
862     UnificationState m_unificationState;
863     PlanStage m_planStage { PlanStage::Initial };
864     RefCountState m_refCountState;
865     bool m_hasDebuggerEnabled;
866 private:
867     
868     void handleSuccessor(Vector<BasicBlock*, 16>& worklist, BasicBlock*, BasicBlock* successor);
869     
870     AddSpeculationMode addImmediateShouldSpeculateInt32(Node* add, bool variableShouldSpeculateInt32, Node* operand, Node*immediate, RareCaseProfilingSource source)
871     {
872         ASSERT(immediate->hasConstant());
873         
874         JSValue immediateValue = immediate->asJSValue();
875         if (!immediateValue.isNumber() && !immediateValue.isBoolean())
876             return DontSpeculateInt32;
877         
878         if (!variableShouldSpeculateInt32)
879             return DontSpeculateInt32;
880
881         // Integer constants can be typed Double if they are written like a double in the source code (e.g. 42.0).
882         // In that case, we stay conservative unless the other operand was explicitly typed as integer.
883         NodeFlags operandResultType = operand->result();
884         if (operandResultType != NodeResultInt32 && immediateValue.isDouble())
885             return DontSpeculateInt32;
886         
887         if (immediateValue.isBoolean() || jsNumber(immediateValue.asNumber()).isInt32())
888             return add->canSpeculateInt32(source) ? SpeculateInt32 : DontSpeculateInt32;
889         
890         double doubleImmediate = immediateValue.asDouble();
891         const double twoToThe48 = 281474976710656.0;
892         if (doubleImmediate < -twoToThe48 || doubleImmediate > twoToThe48)
893             return DontSpeculateInt32;
894         
895         return bytecodeCanTruncateInteger(add->arithNodeFlags()) ? SpeculateInt32AndTruncateConstants : DontSpeculateInt32;
896     }
897 };
898
899 } } // namespace JSC::DFG
900
901 #endif
902 #endif