35b76419e19b8571a2820bd60ee7ae08edae65af
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGByteCodeParser.cpp
1 /*
2  * Copyright (C) 2011-2017 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 #include "config.h"
27 #include "DFGByteCodeParser.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "ArithProfile.h"
32 #include "ArrayConstructor.h"
33 #include "BasicBlockLocation.h"
34 #include "BytecodeStructs.h"
35 #include "CallLinkStatus.h"
36 #include "CodeBlock.h"
37 #include "CodeBlockWithJITType.h"
38 #include "CommonSlowPaths.h"
39 #include "DFGAbstractHeap.h"
40 #include "DFGArrayMode.h"
41 #include "DFGCFG.h"
42 #include "DFGCapabilities.h"
43 #include "DFGClobberize.h"
44 #include "DFGClobbersExitState.h"
45 #include "DFGGraph.h"
46 #include "DFGJITCode.h"
47 #include "FunctionCodeBlock.h"
48 #include "GetByIdStatus.h"
49 #include "Heap.h"
50 #include "JSCInlines.h"
51 #include "JSModuleEnvironment.h"
52 #include "JSModuleNamespaceObject.h"
53 #include "NumberConstructor.h"
54 #include "ObjectConstructor.h"
55 #include "PreciseJumpTargets.h"
56 #include "PutByIdFlags.h"
57 #include "PutByIdStatus.h"
58 #include "RegExpPrototype.h"
59 #include "StackAlignment.h"
60 #include "StringConstructor.h"
61 #include "StructureStubInfo.h"
62 #include "Watchdog.h"
63 #include <wtf/CommaPrinter.h>
64 #include <wtf/HashMap.h>
65 #include <wtf/MathExtras.h>
66 #include <wtf/SetForScope.h>
67 #include <wtf/StdLibExtras.h>
68
69 namespace JSC { namespace DFG {
70
71 namespace DFGByteCodeParserInternal {
72 #ifdef NDEBUG
73 static const bool verbose = false;
74 #else
75 static const bool verbose = true;
76 #endif
77 } // namespace DFGByteCodeParserInternal
78
79 #define VERBOSE_LOG(...) do { \
80 if (DFGByteCodeParserInternal::verbose && Options::verboseDFGBytecodeParsing()) \
81 dataLog(__VA_ARGS__); \
82 } while (false)
83
84 class ConstantBufferKey {
85 public:
86     ConstantBufferKey()
87         : m_codeBlock(0)
88         , m_index(0)
89     {
90     }
91     
92     ConstantBufferKey(WTF::HashTableDeletedValueType)
93         : m_codeBlock(0)
94         , m_index(1)
95     {
96     }
97     
98     ConstantBufferKey(CodeBlock* codeBlock, unsigned index)
99         : m_codeBlock(codeBlock)
100         , m_index(index)
101     {
102     }
103     
104     bool operator==(const ConstantBufferKey& other) const
105     {
106         return m_codeBlock == other.m_codeBlock
107             && m_index == other.m_index;
108     }
109     
110     unsigned hash() const
111     {
112         return WTF::PtrHash<CodeBlock*>::hash(m_codeBlock) ^ m_index;
113     }
114     
115     bool isHashTableDeletedValue() const
116     {
117         return !m_codeBlock && m_index;
118     }
119     
120     CodeBlock* codeBlock() const { return m_codeBlock; }
121     unsigned index() const { return m_index; }
122     
123 private:
124     CodeBlock* m_codeBlock;
125     unsigned m_index;
126 };
127
128 struct ConstantBufferKeyHash {
129     static unsigned hash(const ConstantBufferKey& key) { return key.hash(); }
130     static bool equal(const ConstantBufferKey& a, const ConstantBufferKey& b)
131     {
132         return a == b;
133     }
134     
135     static const bool safeToCompareToEmptyOrDeleted = true;
136 };
137
138 } } // namespace JSC::DFG
139
140 namespace WTF {
141
142 template<typename T> struct DefaultHash;
143 template<> struct DefaultHash<JSC::DFG::ConstantBufferKey> {
144     typedef JSC::DFG::ConstantBufferKeyHash Hash;
145 };
146
147 template<typename T> struct HashTraits;
148 template<> struct HashTraits<JSC::DFG::ConstantBufferKey> : SimpleClassHashTraits<JSC::DFG::ConstantBufferKey> { };
149
150 } // namespace WTF
151
152 namespace JSC { namespace DFG {
153
154 // === ByteCodeParser ===
155 //
156 // This class is used to compile the dataflow graph from a CodeBlock.
157 class ByteCodeParser {
158 public:
159     ByteCodeParser(Graph& graph)
160         : m_vm(&graph.m_vm)
161         , m_codeBlock(graph.m_codeBlock)
162         , m_profiledBlock(graph.m_profiledBlock)
163         , m_graph(graph)
164         , m_currentBlock(0)
165         , m_currentIndex(0)
166         , m_constantUndefined(graph.freeze(jsUndefined()))
167         , m_constantNull(graph.freeze(jsNull()))
168         , m_constantNaN(graph.freeze(jsNumber(PNaN)))
169         , m_constantOne(graph.freeze(jsNumber(1)))
170         , m_numArguments(m_codeBlock->numParameters())
171         , m_numLocals(m_codeBlock->m_numCalleeLocals)
172         , m_parameterSlots(0)
173         , m_numPassedVarArgs(0)
174         , m_inlineStackTop(0)
175         , m_currentInstruction(0)
176         , m_hasDebuggerEnabled(graph.hasDebuggerEnabled())
177     {
178         ASSERT(m_profiledBlock);
179     }
180     
181     // Parse a full CodeBlock of bytecode.
182     void parse();
183     
184 private:
185     struct InlineStackEntry;
186
187     // Just parse from m_currentIndex to the end of the current CodeBlock.
188     void parseCodeBlock();
189     
190     void ensureLocals(unsigned newNumLocals)
191     {
192         VERBOSE_LOG("   ensureLocals: trying to raise m_numLocals from ", m_numLocals, " to ", newNumLocals, "\n");
193         if (newNumLocals <= m_numLocals)
194             return;
195         m_numLocals = newNumLocals;
196         for (size_t i = 0; i < m_graph.numBlocks(); ++i)
197             m_graph.block(i)->ensureLocals(newNumLocals);
198     }
199
200     // Helper for min and max.
201     template<typename ChecksFunctor>
202     bool handleMinMax(int resultOperand, NodeType op, int registerOffset, int argumentCountIncludingThis, const ChecksFunctor& insertChecks);
203     
204     void refineStatically(CallLinkStatus&, Node* callTarget);
205     // Blocks can either be targetable (i.e. in the m_blockLinkingTargets of one InlineStackEntry) with a well-defined bytecodeBegin,
206     // or they can be untargetable, with bytecodeBegin==UINT_MAX, to be managed manually and not by the linkBlock machinery.
207     // This is used most notably when doing polyvariant inlining (it requires a fair bit of control-flow with no bytecode analog).
208     // It is also used when doing an early return from an inlined callee: it is easier to fix the bytecode index later on if needed
209     // than to move the right index all the way to the treatment of op_ret.
210     BasicBlock* allocateTargetableBlock(unsigned bytecodeIndex);
211     BasicBlock* allocateUntargetableBlock();
212     // An untargetable block can be given a bytecodeIndex to be later managed by linkBlock, but only once, and it can never go in the other direction
213     void makeBlockTargetable(BasicBlock*, unsigned bytecodeIndex);
214     void addJumpTo(BasicBlock*);
215     void addJumpTo(unsigned bytecodeIndex);
216     // Handle calls. This resolves issues surrounding inlining and intrinsics.
217     enum Terminality { Terminal, NonTerminal };
218     Terminality handleCall(
219         int result, NodeType op, InlineCallFrame::Kind, unsigned instructionSize,
220         Node* callTarget, int argumentCountIncludingThis, int registerOffset, CallLinkStatus,
221         SpeculatedType prediction);
222     Terminality handleCall(Instruction* pc, NodeType op, CallMode);
223     Terminality handleVarargsCall(Instruction* pc, NodeType op, CallMode);
224     void emitFunctionChecks(CallVariant, Node* callTarget, VirtualRegister thisArgumnt);
225     void emitArgumentPhantoms(int registerOffset, int argumentCountIncludingThis);
226     Node* getArgumentCount();
227     bool handleRecursiveTailCall(Node* callTargetNode, const CallLinkStatus&, int registerOffset, VirtualRegister thisArgument, int argumentCountIncludingThis);
228     unsigned inliningCost(CallVariant, int argumentCountIncludingThis, InlineCallFrame::Kind); // Return UINT_MAX if it's not an inlining candidate. By convention, intrinsics have a cost of 1.
229     // Handle inlining. Return true if it succeeded, false if we need to plant a call.
230     bool handleInlining(Node* callTargetNode, int resultOperand, const CallLinkStatus&, int registerOffset, VirtualRegister thisArgument, VirtualRegister argumentsArgument, unsigned argumentsOffset, int argumentCountIncludingThis, unsigned nextOffset, NodeType callOp, InlineCallFrame::Kind, SpeculatedType prediction);
231     template<typename ChecksFunctor>
232     bool attemptToInlineCall(Node* callTargetNode, int resultOperand, CallVariant, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, InlineCallFrame::Kind, SpeculatedType prediction, unsigned& inliningBalance, BasicBlock* continuationBlock, const ChecksFunctor& insertChecks);
233     template<typename ChecksFunctor>
234     void inlineCall(Node* callTargetNode, int resultOperand, CallVariant, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, InlineCallFrame::Kind, BasicBlock* continuationBlock, const ChecksFunctor& insertChecks);
235     // Handle intrinsic functions. Return true if it succeeded, false if we need to plant a call.
236     template<typename ChecksFunctor>
237     bool handleIntrinsicCall(Node* callee, int resultOperand, Intrinsic, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction, const ChecksFunctor& insertChecks);
238     template<typename ChecksFunctor>
239     bool handleDOMJITCall(Node* callee, int resultOperand, const DOMJIT::Signature*, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction, const ChecksFunctor& insertChecks);
240     template<typename ChecksFunctor>
241     bool handleIntrinsicGetter(int resultOperand, SpeculatedType prediction, const GetByIdVariant& intrinsicVariant, Node* thisNode, const ChecksFunctor& insertChecks);
242     template<typename ChecksFunctor>
243     bool handleTypedArrayConstructor(int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, TypedArrayType, const ChecksFunctor& insertChecks);
244     template<typename ChecksFunctor>
245     bool handleConstantInternalFunction(Node* callTargetNode, int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, CodeSpecializationKind, SpeculatedType, const ChecksFunctor& insertChecks);
246     Node* handlePutByOffset(Node* base, unsigned identifier, PropertyOffset, const InferredType::Descriptor&, Node* value);
247     Node* handleGetByOffset(SpeculatedType, Node* base, unsigned identifierNumber, PropertyOffset, const InferredType::Descriptor&, NodeType = GetByOffset);
248     bool handleDOMJITGetter(int resultOperand, const GetByIdVariant&, Node* thisNode, unsigned identifierNumber, SpeculatedType prediction);
249     bool handleModuleNamespaceLoad(int resultOperand, SpeculatedType, Node* base, GetByIdStatus);
250
251     // Create a presence ObjectPropertyCondition based on some known offset and structure set. Does not
252     // check the validity of the condition, but it may return a null one if it encounters a contradiction.
253     ObjectPropertyCondition presenceLike(
254         JSObject* knownBase, UniquedStringImpl*, PropertyOffset, const StructureSet&);
255     
256     // Attempt to watch the presence of a property. It will watch that the property is present in the same
257     // way as in all of the structures in the set. It may emit code instead of just setting a watchpoint.
258     // Returns true if this all works out.
259     bool checkPresenceLike(JSObject* knownBase, UniquedStringImpl*, PropertyOffset, const StructureSet&);
260     void checkPresenceLike(Node* base, UniquedStringImpl*, PropertyOffset, const StructureSet&);
261     
262     // Works with both GetByIdVariant and the setter form of PutByIdVariant.
263     template<typename VariantType>
264     Node* load(SpeculatedType, Node* base, unsigned identifierNumber, const VariantType&);
265
266     Node* store(Node* base, unsigned identifier, const PutByIdVariant&, Node* value);
267
268     void handleGetById(
269         int destinationOperand, SpeculatedType, Node* base, unsigned identifierNumber, GetByIdStatus, AccessType, unsigned instructionSize);
270     void emitPutById(
271         Node* base, unsigned identifierNumber, Node* value,  const PutByIdStatus&, bool isDirect);
272     void handlePutById(
273         Node* base, unsigned identifierNumber, Node* value, const PutByIdStatus&,
274         bool isDirect);
275     
276     // Either register a watchpoint or emit a check for this condition. Returns false if the
277     // condition no longer holds, and therefore no reasonable check can be emitted.
278     bool check(const ObjectPropertyCondition&);
279     
280     GetByOffsetMethod promoteToConstant(GetByOffsetMethod);
281     
282     // Either register a watchpoint or emit a check for this condition. It must be a Presence
283     // condition. It will attempt to promote a Presence condition to an Equivalence condition.
284     // Emits code for the loaded value that the condition guards, and returns a node containing
285     // the loaded value. Returns null if the condition no longer holds.
286     GetByOffsetMethod planLoad(const ObjectPropertyCondition&);
287     Node* load(SpeculatedType, unsigned identifierNumber, const GetByOffsetMethod&, NodeType = GetByOffset);
288     Node* load(SpeculatedType, const ObjectPropertyCondition&, NodeType = GetByOffset);
289     
290     // Calls check() for each condition in the set: that is, it either emits checks or registers
291     // watchpoints (or a combination of the two) to make the conditions hold. If any of those
292     // conditions are no longer checkable, returns false.
293     bool check(const ObjectPropertyConditionSet&);
294     
295     // Calls check() for those conditions that aren't the slot base, and calls load() for the slot
296     // base. Does a combination of watchpoint registration and check emission to guard the
297     // conditions, and emits code to load the value from the slot base. Returns a node containing
298     // the loaded value. Returns null if any of the conditions were no longer checkable.
299     GetByOffsetMethod planLoad(const ObjectPropertyConditionSet&);
300     Node* load(SpeculatedType, const ObjectPropertyConditionSet&, NodeType = GetByOffset);
301
302     void prepareToParseBlock();
303     void clearCaches();
304
305     // Parse a single basic block of bytecode instructions.
306     void parseBlock(unsigned limit);
307     // Link block successors.
308     void linkBlock(BasicBlock*, Vector<BasicBlock*>& possibleTargets);
309     void linkBlocks(Vector<BasicBlock*>& unlinkedBlocks, Vector<BasicBlock*>& possibleTargets);
310     
311     VariableAccessData* newVariableAccessData(VirtualRegister operand)
312     {
313         ASSERT(!operand.isConstant());
314         
315         m_graph.m_variableAccessData.append(VariableAccessData(operand));
316         return &m_graph.m_variableAccessData.last();
317     }
318     
319     // Get/Set the operands/result of a bytecode instruction.
320     Node* getDirect(VirtualRegister operand)
321     {
322         ASSERT(!operand.isConstant());
323
324         // Is this an argument?
325         if (operand.isArgument())
326             return getArgument(operand);
327
328         // Must be a local.
329         return getLocal(operand);
330     }
331
332     Node* get(VirtualRegister operand)
333     {
334         if (operand.isConstant()) {
335             unsigned constantIndex = operand.toConstantIndex();
336             unsigned oldSize = m_constants.size();
337             if (constantIndex >= oldSize || !m_constants[constantIndex]) {
338                 const CodeBlock& codeBlock = *m_inlineStackTop->m_codeBlock;
339                 JSValue value = codeBlock.getConstant(operand.offset());
340                 SourceCodeRepresentation sourceCodeRepresentation = codeBlock.constantSourceCodeRepresentation(operand.offset());
341                 if (constantIndex >= oldSize) {
342                     m_constants.grow(constantIndex + 1);
343                     for (unsigned i = oldSize; i < m_constants.size(); ++i)
344                         m_constants[i] = nullptr;
345                 }
346
347                 Node* constantNode = nullptr;
348                 if (sourceCodeRepresentation == SourceCodeRepresentation::Double)
349                     constantNode = addToGraph(DoubleConstant, OpInfo(m_graph.freezeStrong(jsDoubleNumber(value.asNumber()))));
350                 else
351                     constantNode = addToGraph(JSConstant, OpInfo(m_graph.freezeStrong(value)));
352                 m_constants[constantIndex] = constantNode;
353             }
354             ASSERT(m_constants[constantIndex]);
355             return m_constants[constantIndex];
356         }
357         
358         if (inlineCallFrame()) {
359             if (!inlineCallFrame()->isClosureCall) {
360                 JSFunction* callee = inlineCallFrame()->calleeConstant();
361                 if (operand.offset() == CallFrameSlot::callee)
362                     return weakJSConstant(callee);
363             }
364         } else if (operand.offset() == CallFrameSlot::callee) {
365             // We have to do some constant-folding here because this enables CreateThis folding. Note
366             // that we don't have such watchpoint-based folding for inlined uses of Callee, since in that
367             // case if the function is a singleton then we already know it.
368             if (FunctionExecutable* executable = jsDynamicCast<FunctionExecutable*>(*m_vm, m_codeBlock->ownerExecutable())) {
369                 InferredValue* singleton = executable->singletonFunction();
370                 if (JSValue value = singleton->inferredValue()) {
371                     m_graph.watchpoints().addLazily(singleton);
372                     JSFunction* function = jsCast<JSFunction*>(value);
373                     return weakJSConstant(function);
374                 }
375             }
376             return addToGraph(GetCallee);
377         }
378         
379         return getDirect(m_inlineStackTop->remapOperand(operand));
380     }
381     
382     enum SetMode {
383         // A normal set which follows a two-phase commit that spans code origins. During
384         // the current code origin it issues a MovHint, and at the start of the next
385         // code origin there will be a SetLocal. If the local needs flushing, the second
386         // SetLocal will be preceded with a Flush.
387         NormalSet,
388         
389         // A set where the SetLocal happens immediately and there is still a Flush. This
390         // is relevant when assigning to a local in tricky situations for the delayed
391         // SetLocal logic but where we know that we have not performed any side effects
392         // within this code origin. This is a safe replacement for NormalSet anytime we
393         // know that we have not yet performed side effects in this code origin.
394         ImmediateSetWithFlush,
395         
396         // A set where the SetLocal happens immediately and we do not Flush it even if
397         // this is a local that is marked as needing it. This is relevant when
398         // initializing locals at the top of a function.
399         ImmediateNakedSet
400     };
401     Node* setDirect(VirtualRegister operand, Node* value, SetMode setMode = NormalSet)
402     {
403         addToGraph(MovHint, OpInfo(operand.offset()), value);
404
405         // We can't exit anymore because our OSR exit state has changed.
406         m_exitOK = false;
407
408         DelayedSetLocal delayed(currentCodeOrigin(), operand, value, setMode);
409         
410         if (setMode == NormalSet) {
411             m_setLocalQueue.append(delayed);
412             return nullptr;
413         }
414         
415         return delayed.execute(this);
416     }
417     
418     void processSetLocalQueue()
419     {
420         for (unsigned i = 0; i < m_setLocalQueue.size(); ++i)
421             m_setLocalQueue[i].execute(this);
422         m_setLocalQueue.shrink(0);
423     }
424
425     Node* set(VirtualRegister operand, Node* value, SetMode setMode = NormalSet)
426     {
427         return setDirect(m_inlineStackTop->remapOperand(operand), value, setMode);
428     }
429     
430     Node* injectLazyOperandSpeculation(Node* node)
431     {
432         ASSERT(node->op() == GetLocal);
433         ASSERT(node->origin.semantic.bytecodeIndex == m_currentIndex);
434         ConcurrentJSLocker locker(m_inlineStackTop->m_profiledBlock->m_lock);
435         LazyOperandValueProfileKey key(m_currentIndex, node->local());
436         SpeculatedType prediction = m_inlineStackTop->m_lazyOperands.prediction(locker, key);
437         node->variableAccessData()->predict(prediction);
438         return node;
439     }
440
441     // Used in implementing get/set, above, where the operand is a local variable.
442     Node* getLocal(VirtualRegister operand)
443     {
444         unsigned local = operand.toLocal();
445
446         Node* node = m_currentBlock->variablesAtTail.local(local);
447         
448         // This has two goals: 1) link together variable access datas, and 2)
449         // try to avoid creating redundant GetLocals. (1) is required for
450         // correctness - no other phase will ensure that block-local variable
451         // access data unification is done correctly. (2) is purely opportunistic
452         // and is meant as an compile-time optimization only.
453         
454         VariableAccessData* variable;
455         
456         if (node) {
457             variable = node->variableAccessData();
458             
459             switch (node->op()) {
460             case GetLocal:
461                 return node;
462             case SetLocal:
463                 return node->child1().node();
464             default:
465                 break;
466             }
467         } else
468             variable = newVariableAccessData(operand);
469         
470         node = injectLazyOperandSpeculation(addToGraph(GetLocal, OpInfo(variable)));
471         m_currentBlock->variablesAtTail.local(local) = node;
472         return node;
473     }
474     Node* setLocal(const CodeOrigin& semanticOrigin, VirtualRegister operand, Node* value, SetMode setMode = NormalSet)
475     {
476         SetForScope<CodeOrigin> originChange(m_currentSemanticOrigin, semanticOrigin);
477
478         unsigned local = operand.toLocal();
479         
480         if (setMode != ImmediateNakedSet) {
481             ArgumentPosition* argumentPosition = findArgumentPositionForLocal(operand);
482             if (argumentPosition)
483                 flushDirect(operand, argumentPosition);
484             else if (m_graph.needsScopeRegister() && operand == m_codeBlock->scopeRegister())
485                 flush(operand);
486         }
487
488         VariableAccessData* variableAccessData = newVariableAccessData(operand);
489         variableAccessData->mergeStructureCheckHoistingFailed(
490             m_inlineStackTop->m_exitProfile.hasExitSite(semanticOrigin.bytecodeIndex, BadCache));
491         variableAccessData->mergeCheckArrayHoistingFailed(
492             m_inlineStackTop->m_exitProfile.hasExitSite(semanticOrigin.bytecodeIndex, BadIndexingType));
493         Node* node = addToGraph(SetLocal, OpInfo(variableAccessData), value);
494         m_currentBlock->variablesAtTail.local(local) = node;
495         return node;
496     }
497
498     // Used in implementing get/set, above, where the operand is an argument.
499     Node* getArgument(VirtualRegister operand)
500     {
501         unsigned argument = operand.toArgument();
502         ASSERT(argument < m_numArguments);
503         
504         Node* node = m_currentBlock->variablesAtTail.argument(argument);
505
506         VariableAccessData* variable;
507         
508         if (node) {
509             variable = node->variableAccessData();
510             
511             switch (node->op()) {
512             case GetLocal:
513                 return node;
514             case SetLocal:
515                 return node->child1().node();
516             default:
517                 break;
518             }
519         } else
520             variable = newVariableAccessData(operand);
521         
522         node = injectLazyOperandSpeculation(addToGraph(GetLocal, OpInfo(variable)));
523         m_currentBlock->variablesAtTail.argument(argument) = node;
524         return node;
525     }
526     Node* setArgument(const CodeOrigin& semanticOrigin, VirtualRegister operand, Node* value, SetMode setMode = NormalSet)
527     {
528         SetForScope<CodeOrigin> originChange(m_currentSemanticOrigin, semanticOrigin);
529
530         unsigned argument = operand.toArgument();
531         ASSERT(argument < m_numArguments);
532         
533         VariableAccessData* variableAccessData = newVariableAccessData(operand);
534
535         // Always flush arguments, except for 'this'. If 'this' is created by us,
536         // then make sure that it's never unboxed.
537         if (argument || m_graph.needsFlushedThis()) {
538             if (setMode != ImmediateNakedSet)
539                 flushDirect(operand);
540         }
541         
542         if (!argument && m_codeBlock->specializationKind() == CodeForConstruct)
543             variableAccessData->mergeShouldNeverUnbox(true);
544         
545         variableAccessData->mergeStructureCheckHoistingFailed(
546             m_inlineStackTop->m_exitProfile.hasExitSite(semanticOrigin.bytecodeIndex, BadCache));
547         variableAccessData->mergeCheckArrayHoistingFailed(
548             m_inlineStackTop->m_exitProfile.hasExitSite(semanticOrigin.bytecodeIndex, BadIndexingType));
549         Node* node = addToGraph(SetLocal, OpInfo(variableAccessData), value);
550         m_currentBlock->variablesAtTail.argument(argument) = node;
551         return node;
552     }
553     
554     ArgumentPosition* findArgumentPositionForArgument(int argument)
555     {
556         InlineStackEntry* stack = m_inlineStackTop;
557         while (stack->m_inlineCallFrame)
558             stack = stack->m_caller;
559         return stack->m_argumentPositions[argument];
560     }
561     
562     ArgumentPosition* findArgumentPositionForLocal(VirtualRegister operand)
563     {
564         for (InlineStackEntry* stack = m_inlineStackTop; ; stack = stack->m_caller) {
565             InlineCallFrame* inlineCallFrame = stack->m_inlineCallFrame;
566             if (!inlineCallFrame)
567                 break;
568             if (operand.offset() < static_cast<int>(inlineCallFrame->stackOffset + CallFrame::headerSizeInRegisters))
569                 continue;
570             if (operand.offset() == inlineCallFrame->stackOffset + CallFrame::thisArgumentOffset())
571                 continue;
572             if (operand.offset() >= static_cast<int>(inlineCallFrame->stackOffset + CallFrame::thisArgumentOffset() + inlineCallFrame->argumentsWithFixup.size()))
573                 continue;
574             int argument = VirtualRegister(operand.offset() - inlineCallFrame->stackOffset).toArgument();
575             return stack->m_argumentPositions[argument];
576         }
577         return 0;
578     }
579     
580     ArgumentPosition* findArgumentPosition(VirtualRegister operand)
581     {
582         if (operand.isArgument())
583             return findArgumentPositionForArgument(operand.toArgument());
584         return findArgumentPositionForLocal(operand);
585     }
586
587     void flush(VirtualRegister operand)
588     {
589         flushDirect(m_inlineStackTop->remapOperand(operand));
590     }
591     
592     void flushDirect(VirtualRegister operand)
593     {
594         flushDirect(operand, findArgumentPosition(operand));
595     }
596
597     void flushDirect(VirtualRegister operand, ArgumentPosition* argumentPosition)
598     {
599         addFlushOrPhantomLocal<Flush>(operand, argumentPosition);
600     }
601
602     template<NodeType nodeType>
603     void addFlushOrPhantomLocal(VirtualRegister operand, ArgumentPosition* argumentPosition)
604     {
605         ASSERT(!operand.isConstant());
606         
607         Node* node = m_currentBlock->variablesAtTail.operand(operand);
608         
609         VariableAccessData* variable;
610         
611         if (node)
612             variable = node->variableAccessData();
613         else
614             variable = newVariableAccessData(operand);
615         
616         node = addToGraph(nodeType, OpInfo(variable));
617         m_currentBlock->variablesAtTail.operand(operand) = node;
618         if (argumentPosition)
619             argumentPosition->addVariable(variable);
620     }
621
622     void phantomLocalDirect(VirtualRegister operand)
623     {
624         addFlushOrPhantomLocal<PhantomLocal>(operand, findArgumentPosition(operand));
625     }
626
627     void flush(InlineStackEntry* inlineStackEntry)
628     {
629         int numArguments;
630         if (InlineCallFrame* inlineCallFrame = inlineStackEntry->m_inlineCallFrame) {
631             ASSERT(!m_hasDebuggerEnabled);
632             numArguments = inlineCallFrame->argumentsWithFixup.size();
633             if (inlineCallFrame->isClosureCall)
634                 flushDirect(inlineStackEntry->remapOperand(VirtualRegister(CallFrameSlot::callee)));
635             if (inlineCallFrame->isVarargs())
636                 flushDirect(inlineStackEntry->remapOperand(VirtualRegister(CallFrameSlot::argumentCount)));
637         } else
638             numArguments = inlineStackEntry->m_codeBlock->numParameters();
639         for (unsigned argument = numArguments; argument-- > 1;)
640             flushDirect(inlineStackEntry->remapOperand(virtualRegisterForArgument(argument)));
641         if (!inlineStackEntry->m_inlineCallFrame && m_graph.needsFlushedThis())
642             flushDirect(virtualRegisterForArgument(0));
643
644         if (m_graph.needsScopeRegister())
645             flushDirect(m_codeBlock->scopeRegister());
646     }
647
648     void flushForTerminal()
649     {
650         CodeOrigin origin = currentCodeOrigin();
651         unsigned bytecodeIndex = origin.bytecodeIndex;
652
653         for (InlineStackEntry* inlineStackEntry = m_inlineStackTop; inlineStackEntry; inlineStackEntry = inlineStackEntry->m_caller) {
654             flush(inlineStackEntry);
655
656             ASSERT(origin.inlineCallFrame == inlineStackEntry->m_inlineCallFrame);
657             InlineCallFrame* inlineCallFrame = inlineStackEntry->m_inlineCallFrame;
658             CodeBlock* codeBlock = m_graph.baselineCodeBlockFor(inlineCallFrame);
659             FullBytecodeLiveness& fullLiveness = m_graph.livenessFor(codeBlock);
660             const FastBitVector& livenessAtBytecode = fullLiveness.getLiveness(bytecodeIndex);
661
662             for (unsigned local = codeBlock->m_numCalleeLocals; local--;) {
663                 if (livenessAtBytecode[local]) {
664                     VirtualRegister reg = virtualRegisterForLocal(local);
665                     if (inlineCallFrame)
666                         reg = inlineStackEntry->remapOperand(reg);
667                     phantomLocalDirect(reg);
668                 }
669             }
670
671             if (inlineCallFrame) {
672                 bytecodeIndex = inlineCallFrame->directCaller.bytecodeIndex;
673                 origin = inlineCallFrame->directCaller;
674             }
675         }
676     }
677
678     void flushForReturn()
679     {
680         flush(m_inlineStackTop);
681     }
682     
683     void flushIfTerminal(SwitchData& data)
684     {
685         if (data.fallThrough.bytecodeIndex() > m_currentIndex)
686             return;
687         
688         for (unsigned i = data.cases.size(); i--;) {
689             if (data.cases[i].target.bytecodeIndex() > m_currentIndex)
690                 return;
691         }
692         
693         flushForTerminal();
694     }
695
696     // Assumes that the constant should be strongly marked.
697     Node* jsConstant(JSValue constantValue)
698     {
699         return addToGraph(JSConstant, OpInfo(m_graph.freezeStrong(constantValue)));
700     }
701
702     Node* weakJSConstant(JSValue constantValue)
703     {
704         return addToGraph(JSConstant, OpInfo(m_graph.freeze(constantValue)));
705     }
706
707     // Helper functions to get/set the this value.
708     Node* getThis()
709     {
710         return get(m_inlineStackTop->m_codeBlock->thisRegister());
711     }
712
713     void setThis(Node* value)
714     {
715         set(m_inlineStackTop->m_codeBlock->thisRegister(), value);
716     }
717
718     InlineCallFrame* inlineCallFrame()
719     {
720         return m_inlineStackTop->m_inlineCallFrame;
721     }
722
723     bool allInlineFramesAreTailCalls()
724     {
725         return !inlineCallFrame() || !inlineCallFrame()->getCallerSkippingTailCalls();
726     }
727
728     CodeOrigin currentCodeOrigin()
729     {
730         return CodeOrigin(m_currentIndex, inlineCallFrame());
731     }
732
733     NodeOrigin currentNodeOrigin()
734     {
735         CodeOrigin semantic;
736         CodeOrigin forExit;
737
738         if (m_currentSemanticOrigin.isSet())
739             semantic = m_currentSemanticOrigin;
740         else
741             semantic = currentCodeOrigin();
742
743         forExit = currentCodeOrigin();
744
745         return NodeOrigin(semantic, forExit, m_exitOK);
746     }
747     
748     BranchData* branchData(unsigned taken, unsigned notTaken)
749     {
750         // We assume that branches originating from bytecode always have a fall-through. We
751         // use this assumption to avoid checking for the creation of terminal blocks.
752         ASSERT((taken > m_currentIndex) || (notTaken > m_currentIndex));
753         BranchData* data = m_graph.m_branchData.add();
754         *data = BranchData::withBytecodeIndices(taken, notTaken);
755         return data;
756     }
757     
758     Node* addToGraph(Node* node)
759     {
760         VERBOSE_LOG("        appended ", node, " ", Graph::opName(node->op()), "\n");
761         m_currentBlock->append(node);
762         if (clobbersExitState(m_graph, node))
763             m_exitOK = false;
764         return node;
765     }
766     
767     Node* addToGraph(NodeType op, Node* child1 = 0, Node* child2 = 0, Node* child3 = 0)
768     {
769         Node* result = m_graph.addNode(
770             op, currentNodeOrigin(), Edge(child1), Edge(child2),
771             Edge(child3));
772         return addToGraph(result);
773     }
774     Node* addToGraph(NodeType op, Edge child1, Edge child2 = Edge(), Edge child3 = Edge())
775     {
776         Node* result = m_graph.addNode(
777             op, currentNodeOrigin(), child1, child2, child3);
778         return addToGraph(result);
779     }
780     Node* addToGraph(NodeType op, OpInfo info, Node* child1 = 0, Node* child2 = 0, Node* child3 = 0)
781     {
782         Node* result = m_graph.addNode(
783             op, currentNodeOrigin(), info, Edge(child1), Edge(child2),
784             Edge(child3));
785         return addToGraph(result);
786     }
787     Node* addToGraph(NodeType op, OpInfo info, Edge child1, Edge child2 = Edge(), Edge child3 = Edge())
788     {
789         Node* result = m_graph.addNode(op, currentNodeOrigin(), info, child1, child2, child3);
790         return addToGraph(result);
791     }
792     Node* addToGraph(NodeType op, OpInfo info1, OpInfo info2, Node* child1 = 0, Node* child2 = 0, Node* child3 = 0)
793     {
794         Node* result = m_graph.addNode(
795             op, currentNodeOrigin(), info1, info2,
796             Edge(child1), Edge(child2), Edge(child3));
797         return addToGraph(result);
798     }
799     Node* addToGraph(NodeType op, OpInfo info1, OpInfo info2, Edge child1, Edge child2 = Edge(), Edge child3 = Edge())
800     {
801         Node* result = m_graph.addNode(
802             op, currentNodeOrigin(), info1, info2, child1, child2, child3);
803         return addToGraph(result);
804     }
805     
806     Node* addToGraph(Node::VarArgTag, NodeType op, OpInfo info1, OpInfo info2 = OpInfo())
807     {
808         Node* result = m_graph.addNode(
809             Node::VarArg, op, currentNodeOrigin(), info1, info2,
810             m_graph.m_varArgChildren.size() - m_numPassedVarArgs, m_numPassedVarArgs);
811         addToGraph(result);
812         
813         m_numPassedVarArgs = 0;
814         
815         return result;
816     }
817     
818     void addVarArgChild(Node* child)
819     {
820         m_graph.m_varArgChildren.append(Edge(child));
821         m_numPassedVarArgs++;
822     }
823     
824     Node* addCallWithoutSettingResult(
825         NodeType op, OpInfo opInfo, Node* callee, int argCount, int registerOffset,
826         OpInfo prediction)
827     {
828         addVarArgChild(callee);
829         size_t parameterSlots = Graph::parameterSlotsForArgCount(argCount);
830
831         if (parameterSlots > m_parameterSlots)
832             m_parameterSlots = parameterSlots;
833
834         for (int i = 0; i < argCount; ++i)
835             addVarArgChild(get(virtualRegisterForArgument(i, registerOffset)));
836
837         return addToGraph(Node::VarArg, op, opInfo, prediction);
838     }
839     
840     Node* addCall(
841         int result, NodeType op, const DOMJIT::Signature* signature, Node* callee, int argCount, int registerOffset,
842         SpeculatedType prediction)
843     {
844         if (op == TailCall) {
845             if (allInlineFramesAreTailCalls())
846                 return addCallWithoutSettingResult(op, OpInfo(signature), callee, argCount, registerOffset, OpInfo());
847             op = TailCallInlinedCaller;
848         }
849
850
851         Node* call = addCallWithoutSettingResult(
852             op, OpInfo(signature), callee, argCount, registerOffset, OpInfo(prediction));
853         VirtualRegister resultReg(result);
854         if (resultReg.isValid())
855             set(resultReg, call);
856         return call;
857     }
858     
859     Node* cellConstantWithStructureCheck(JSCell* object, Structure* structure)
860     {
861         // FIXME: This should route to emitPropertyCheck, not the other way around. But currently,
862         // this gets no profit from using emitPropertyCheck() since we'll non-adaptively watch the
863         // object's structure as soon as we make it a weakJSCosntant.
864         Node* objectNode = weakJSConstant(object);
865         addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(structure)), objectNode);
866         return objectNode;
867     }
868     
869     SpeculatedType getPredictionWithoutOSRExit(unsigned bytecodeIndex)
870     {
871         SpeculatedType prediction;
872         {
873             ConcurrentJSLocker locker(m_inlineStackTop->m_profiledBlock->m_lock);
874             prediction = m_inlineStackTop->m_profiledBlock->valueProfilePredictionForBytecodeOffset(locker, bytecodeIndex);
875         }
876
877         if (prediction != SpecNone)
878             return prediction;
879
880         // If we have no information about the values this
881         // node generates, we check if by any chance it is
882         // a tail call opcode. In that case, we walk up the
883         // inline frames to find a call higher in the call
884         // chain and use its prediction. If we only have
885         // inlined tail call frames, we use SpecFullTop
886         // to avoid a spurious OSR exit.
887         Instruction* instruction = m_inlineStackTop->m_profiledBlock->instructions().begin() + bytecodeIndex;
888         OpcodeID opcodeID = Interpreter::getOpcodeID(instruction->u.opcode);
889
890         switch (opcodeID) {
891         case op_tail_call:
892         case op_tail_call_varargs:
893         case op_tail_call_forward_arguments: {
894             // Things should be more permissive to us returning BOTTOM instead of TOP here.
895             // Currently, this will cause us to Force OSR exit. This is bad because returning
896             // TOP will cause anything that transitively touches this speculated type to
897             // also become TOP during prediction propagation.
898             // https://bugs.webkit.org/show_bug.cgi?id=164337
899             if (!inlineCallFrame())
900                 return SpecFullTop;
901
902             CodeOrigin* codeOrigin = inlineCallFrame()->getCallerSkippingTailCalls();
903             if (!codeOrigin)
904                 return SpecFullTop;
905
906             InlineStackEntry* stack = m_inlineStackTop;
907             while (stack->m_inlineCallFrame != codeOrigin->inlineCallFrame)
908                 stack = stack->m_caller;
909
910             bytecodeIndex = codeOrigin->bytecodeIndex;
911             CodeBlock* profiledBlock = stack->m_profiledBlock;
912             ConcurrentJSLocker locker(profiledBlock->m_lock);
913             return profiledBlock->valueProfilePredictionForBytecodeOffset(locker, bytecodeIndex);
914         }
915
916         default:
917             return SpecNone;
918         }
919
920         RELEASE_ASSERT_NOT_REACHED();
921         return SpecNone;
922     }
923
924     SpeculatedType getPrediction(unsigned bytecodeIndex)
925     {
926         SpeculatedType prediction = getPredictionWithoutOSRExit(bytecodeIndex);
927
928         if (prediction == SpecNone) {
929             // We have no information about what values this node generates. Give up
930             // on executing this code, since we're likely to do more damage than good.
931             addToGraph(ForceOSRExit);
932         }
933         
934         return prediction;
935     }
936     
937     SpeculatedType getPredictionWithoutOSRExit()
938     {
939         return getPredictionWithoutOSRExit(m_currentIndex);
940     }
941     
942     SpeculatedType getPrediction()
943     {
944         return getPrediction(m_currentIndex);
945     }
946     
947     ArrayMode getArrayMode(ArrayProfile* profile, Array::Action action)
948     {
949         ConcurrentJSLocker locker(m_inlineStackTop->m_profiledBlock->m_lock);
950         profile->computeUpdatedPrediction(locker, m_inlineStackTop->m_profiledBlock);
951         bool makeSafe = profile->outOfBounds(locker);
952         return ArrayMode::fromObserved(locker, profile, action, makeSafe);
953     }
954     
955     ArrayMode getArrayMode(ArrayProfile* profile)
956     {
957         return getArrayMode(profile, Array::Read);
958     }
959     
960     Node* makeSafe(Node* node)
961     {
962         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
963             node->mergeFlags(NodeMayOverflowInt32InDFG);
964         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero))
965             node->mergeFlags(NodeMayNegZeroInDFG);
966         
967         if (!isX86() && node->op() == ArithMod)
968             return node;
969
970         {
971             ArithProfile* arithProfile = m_inlineStackTop->m_profiledBlock->arithProfileForBytecodeOffset(m_currentIndex);
972             if (arithProfile) {
973                 switch (node->op()) {
974                 case ArithAdd:
975                 case ArithSub:
976                 case ValueAdd:
977                     if (arithProfile->didObserveDouble())
978                         node->mergeFlags(NodeMayHaveDoubleResult);
979                     if (arithProfile->didObserveNonNumber())
980                         node->mergeFlags(NodeMayHaveNonNumberResult);
981                     break;
982                 
983                 case ArithMul: {
984                     if (arithProfile->didObserveInt52Overflow())
985                         node->mergeFlags(NodeMayOverflowInt52);
986                     if (arithProfile->didObserveInt32Overflow() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
987                         node->mergeFlags(NodeMayOverflowInt32InBaseline);
988                     if (arithProfile->didObserveNegZeroDouble() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero))
989                         node->mergeFlags(NodeMayNegZeroInBaseline);
990                     if (arithProfile->didObserveDouble())
991                         node->mergeFlags(NodeMayHaveDoubleResult);
992                     if (arithProfile->didObserveNonNumber())
993                         node->mergeFlags(NodeMayHaveNonNumberResult);
994                     break;
995                 }
996                 case ArithNegate: {
997                     ASSERT_WITH_MESSAGE(!arithProfile->didObserveNonNumber(), "op_negate starts with a toNumber() on the argument, it should only produce numbers.");
998
999                     if (arithProfile->lhsObservedType().sawNumber() || arithProfile->didObserveDouble())
1000                         node->mergeFlags(NodeMayHaveDoubleResult);
1001                     if (arithProfile->didObserveNegZeroDouble() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero))
1002                         node->mergeFlags(NodeMayNegZeroInBaseline);
1003                     if (arithProfile->didObserveInt32Overflow() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
1004                         node->mergeFlags(NodeMayOverflowInt32InBaseline);
1005                     break;
1006                 }
1007                 
1008                 default:
1009                     break;
1010                 }
1011             }
1012         }
1013         
1014         if (m_inlineStackTop->m_profiledBlock->likelyToTakeSlowCase(m_currentIndex)) {
1015             switch (node->op()) {
1016             case UInt32ToNumber:
1017             case ArithAdd:
1018             case ArithSub:
1019             case ValueAdd:
1020             case ArithMod: // for ArithMod "MayOverflow" means we tried to divide by zero, or we saw double.
1021                 node->mergeFlags(NodeMayOverflowInt32InBaseline);
1022                 break;
1023                 
1024             default:
1025                 break;
1026             }
1027         }
1028         
1029         return node;
1030     }
1031     
1032     Node* makeDivSafe(Node* node)
1033     {
1034         ASSERT(node->op() == ArithDiv);
1035         
1036         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
1037             node->mergeFlags(NodeMayOverflowInt32InDFG);
1038         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero))
1039             node->mergeFlags(NodeMayNegZeroInDFG);
1040         
1041         // The main slow case counter for op_div in the old JIT counts only when
1042         // the operands are not numbers. We don't care about that since we already
1043         // have speculations in place that take care of that separately. We only
1044         // care about when the outcome of the division is not an integer, which
1045         // is what the special fast case counter tells us.
1046         
1047         if (!m_inlineStackTop->m_profiledBlock->couldTakeSpecialFastCase(m_currentIndex))
1048             return node;
1049         
1050         // FIXME: It might be possible to make this more granular.
1051         node->mergeFlags(NodeMayOverflowInt32InBaseline | NodeMayNegZeroInBaseline);
1052         
1053         return node;
1054     }
1055     
1056     void noticeArgumentsUse()
1057     {
1058         // All of the arguments in this function need to be formatted as JSValues because we will
1059         // load from them in a random-access fashion and we don't want to have to switch on
1060         // format.
1061         
1062         for (ArgumentPosition* argument : m_inlineStackTop->m_argumentPositions)
1063             argument->mergeShouldNeverUnbox(true);
1064     }
1065
1066     bool needsDynamicLookup(ResolveType, OpcodeID);
1067     
1068     VM* m_vm;
1069     CodeBlock* m_codeBlock;
1070     CodeBlock* m_profiledBlock;
1071     Graph& m_graph;
1072
1073     // The current block being generated.
1074     BasicBlock* m_currentBlock;
1075     // The bytecode index of the current instruction being generated.
1076     unsigned m_currentIndex;
1077     // The semantic origin of the current node if different from the current Index.
1078     CodeOrigin m_currentSemanticOrigin;
1079     // True if it's OK to OSR exit right now.
1080     bool m_exitOK { false };
1081
1082     FrozenValue* m_constantUndefined;
1083     FrozenValue* m_constantNull;
1084     FrozenValue* m_constantNaN;
1085     FrozenValue* m_constantOne;
1086     Vector<Node*, 16> m_constants;
1087
1088     // The number of arguments passed to the function.
1089     unsigned m_numArguments;
1090     // The number of locals (vars + temporaries) used in the function.
1091     unsigned m_numLocals;
1092     // The number of slots (in units of sizeof(Register)) that we need to
1093     // preallocate for arguments to outgoing calls from this frame. This
1094     // number includes the CallFrame slots that we initialize for the callee
1095     // (but not the callee-initialized CallerFrame and ReturnPC slots).
1096     // This number is 0 if and only if this function is a leaf.
1097     unsigned m_parameterSlots;
1098     // The number of var args passed to the next var arg node.
1099     unsigned m_numPassedVarArgs;
1100
1101     HashMap<ConstantBufferKey, unsigned> m_constantBufferCache;
1102     
1103     struct InlineStackEntry {
1104         ByteCodeParser* m_byteCodeParser;
1105         
1106         CodeBlock* m_codeBlock;
1107         CodeBlock* m_profiledBlock;
1108         InlineCallFrame* m_inlineCallFrame;
1109         
1110         ScriptExecutable* executable() { return m_codeBlock->ownerScriptExecutable(); }
1111         
1112         QueryableExitProfile m_exitProfile;
1113         
1114         // Remapping of identifier and constant numbers from the code block being
1115         // inlined (inline callee) to the code block that we're inlining into
1116         // (the machine code block, which is the transitive, though not necessarily
1117         // direct, caller).
1118         Vector<unsigned> m_identifierRemap;
1119         Vector<unsigned> m_constantBufferRemap;
1120         Vector<unsigned> m_switchRemap;
1121         
1122         // These are blocks whose terminal is a Jump, Branch or Switch, and whose target has not yet been linked.
1123         // Their terminal instead refers to a bytecode index, and the right BB can be found in m_blockLinkingTargets.
1124         Vector<BasicBlock*> m_unlinkedBlocks;
1125         
1126         // Potential block linking targets. Must be sorted by bytecodeBegin, and
1127         // cannot have two blocks that have the same bytecodeBegin.
1128         Vector<BasicBlock*> m_blockLinkingTargets;
1129
1130         // Optional: a continuation block for returns to jump to. It is set by early returns if it does not exist.
1131         BasicBlock* m_continuationBlock;
1132
1133         VirtualRegister m_returnValue;
1134         
1135         // Speculations about variable types collected from the profiled code block,
1136         // which are based on OSR exit profiles that past DFG compilations of this
1137         // code block had gathered.
1138         LazyOperandValueProfileParser m_lazyOperands;
1139         
1140         CallLinkInfoMap m_callLinkInfos;
1141         StubInfoMap m_stubInfos;
1142         ByValInfoMap m_byValInfos;
1143         
1144         // Pointers to the argument position trackers for this slice of code.
1145         Vector<ArgumentPosition*> m_argumentPositions;
1146         
1147         InlineStackEntry* m_caller;
1148         
1149         InlineStackEntry(
1150             ByteCodeParser*,
1151             CodeBlock*,
1152             CodeBlock* profiledBlock,
1153             JSFunction* callee, // Null if this is a closure call.
1154             VirtualRegister returnValueVR,
1155             VirtualRegister inlineCallFrameStart,
1156             int argumentCountIncludingThis,
1157             InlineCallFrame::Kind,
1158             BasicBlock* continuationBlock);
1159         
1160         ~InlineStackEntry()
1161         {
1162             m_byteCodeParser->m_inlineStackTop = m_caller;
1163         }
1164         
1165         VirtualRegister remapOperand(VirtualRegister operand) const
1166         {
1167             if (!m_inlineCallFrame)
1168                 return operand;
1169             
1170             ASSERT(!operand.isConstant());
1171
1172             return VirtualRegister(operand.offset() + m_inlineCallFrame->stackOffset);
1173         }
1174     };
1175     
1176     InlineStackEntry* m_inlineStackTop;
1177     
1178     struct DelayedSetLocal {
1179         CodeOrigin m_origin;
1180         VirtualRegister m_operand;
1181         Node* m_value;
1182         SetMode m_setMode;
1183         
1184         DelayedSetLocal() { }
1185         DelayedSetLocal(const CodeOrigin& origin, VirtualRegister operand, Node* value, SetMode setMode)
1186             : m_origin(origin)
1187             , m_operand(operand)
1188             , m_value(value)
1189             , m_setMode(setMode)
1190         {
1191             RELEASE_ASSERT(operand.isValid());
1192         }
1193         
1194         Node* execute(ByteCodeParser* parser)
1195         {
1196             if (m_operand.isArgument())
1197                 return parser->setArgument(m_origin, m_operand, m_value, m_setMode);
1198             return parser->setLocal(m_origin, m_operand, m_value, m_setMode);
1199         }
1200     };
1201     
1202     Vector<DelayedSetLocal, 2> m_setLocalQueue;
1203
1204     CodeBlock* m_dfgCodeBlock;
1205     CallLinkStatus::ContextMap m_callContextMap;
1206     StubInfoMap m_dfgStubInfos;
1207     
1208     Instruction* m_currentInstruction;
1209     bool m_hasDebuggerEnabled;
1210 };
1211
1212 BasicBlock* ByteCodeParser::allocateTargetableBlock(unsigned bytecodeIndex)
1213 {
1214     ASSERT(bytecodeIndex != UINT_MAX);
1215     Ref<BasicBlock> block = adoptRef(*new BasicBlock(bytecodeIndex, m_numArguments, m_numLocals, 1));
1216     BasicBlock* blockPtr = block.ptr();
1217     // m_blockLinkingTargets must always be sorted in increasing order of bytecodeBegin
1218     if (m_inlineStackTop->m_blockLinkingTargets.size())
1219         ASSERT(m_inlineStackTop->m_blockLinkingTargets.last()->bytecodeBegin < bytecodeIndex);
1220     m_inlineStackTop->m_blockLinkingTargets.append(blockPtr);
1221     m_graph.appendBlock(WTFMove(block));
1222     return blockPtr;
1223 }
1224
1225 BasicBlock* ByteCodeParser::allocateUntargetableBlock()
1226 {
1227     Ref<BasicBlock> block = adoptRef(*new BasicBlock(UINT_MAX, m_numArguments, m_numLocals, 1));
1228     BasicBlock* blockPtr = block.ptr();
1229     m_graph.appendBlock(WTFMove(block));
1230     return blockPtr;
1231 }
1232
1233 void ByteCodeParser::makeBlockTargetable(BasicBlock* block, unsigned bytecodeIndex)
1234 {
1235     ASSERT(block->bytecodeBegin == UINT_MAX);
1236     block->bytecodeBegin = bytecodeIndex;
1237     // m_blockLinkingTargets must always be sorted in increasing order of bytecodeBegin
1238     if (m_inlineStackTop->m_blockLinkingTargets.size())
1239         ASSERT(m_inlineStackTop->m_blockLinkingTargets.last()->bytecodeBegin < bytecodeIndex);
1240     m_inlineStackTop->m_blockLinkingTargets.append(block);
1241 }
1242
1243 void ByteCodeParser::addJumpTo(BasicBlock* block)
1244 {
1245     ASSERT(!m_currentBlock->terminal());
1246     Node* jumpNode = addToGraph(Jump);
1247     jumpNode->targetBlock() = block;
1248     m_currentBlock->didLink();
1249 }
1250
1251 void ByteCodeParser::addJumpTo(unsigned bytecodeIndex)
1252 {
1253     ASSERT(!m_currentBlock->terminal());
1254     addToGraph(Jump, OpInfo(bytecodeIndex));
1255     m_inlineStackTop->m_unlinkedBlocks.append(m_currentBlock);
1256 }
1257
1258 ByteCodeParser::Terminality ByteCodeParser::handleCall(Instruction* pc, NodeType op, CallMode callMode)
1259 {
1260     static_assert(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct),
1261         "op_call, op_tail_call and op_construct should always have the same length");
1262     static_assert(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_tail_call),
1263         "op_call, op_tail_call and op_construct should always have the same length");
1264     
1265     int result = pc[1].u.operand;
1266     Node* callTarget = get(VirtualRegister(pc[2].u.operand));
1267     int argumentCountIncludingThis = pc[3].u.operand;
1268     int registerOffset = -pc[4].u.operand;
1269
1270     CallLinkStatus callLinkStatus = CallLinkStatus::computeFor(
1271         m_inlineStackTop->m_profiledBlock, currentCodeOrigin(),
1272         m_inlineStackTop->m_callLinkInfos, m_callContextMap);
1273
1274     InlineCallFrame::Kind kind = InlineCallFrame::kindFor(callMode);
1275
1276     return handleCall(result, op, kind, OPCODE_LENGTH(op_call), callTarget,
1277         argumentCountIncludingThis, registerOffset, callLinkStatus, getPrediction());
1278 }
1279
1280 void ByteCodeParser::refineStatically(CallLinkStatus& callLinkStatus, Node* callTarget)
1281 {
1282     if (callTarget->isCellConstant())
1283         callLinkStatus.setProvenConstantCallee(CallVariant(callTarget->asCell()));
1284 }
1285
1286 ByteCodeParser::Terminality ByteCodeParser::handleCall(
1287     int result, NodeType op, InlineCallFrame::Kind kind, unsigned instructionSize,
1288     Node* callTarget, int argumentCountIncludingThis, int registerOffset,
1289     CallLinkStatus callLinkStatus, SpeculatedType prediction)
1290 {
1291     ASSERT(registerOffset <= 0);
1292
1293     refineStatically(callLinkStatus, callTarget);
1294     
1295     VERBOSE_LOG("    Handling call at ", currentCodeOrigin(), ": ", callLinkStatus, "\n");
1296     
1297     // We first check that we have profiling information about this call, and that it did not behave too polymorphically.
1298     if (callLinkStatus.canOptimize()) {
1299         VirtualRegister thisArgument = virtualRegisterForArgument(0, registerOffset);
1300
1301         if (op == TailCall && handleRecursiveTailCall(callTarget, callLinkStatus, registerOffset, thisArgument, argumentCountIncludingThis))
1302             return Terminal;
1303
1304         // Inlining is quite complex, and managed by a pipeline of functions:
1305         // handle(Varargs)Call -> handleInlining -> attemptToInlineCall -> inlineCall
1306         // - handleCall and handleVarargsCall deal with the case where no inlining happens, and do some sanity checks on their arguments
1307         // - handleInlining checks whether the call is polymorphic, and if so is responsible for inserting a switch on the callee
1308         // - attemptToInlineCall deals with special cases such as intrinsics, it also checks the inlining heuristic (through inliningCost)
1309         // - inlineCall finally does the actual inlining, after a complicated procedure to setup the stack correctly
1310         unsigned nextOffset = m_currentIndex + instructionSize;
1311         if (handleInlining(callTarget, result, callLinkStatus, registerOffset, thisArgument, VirtualRegister(), 0, argumentCountIncludingThis, nextOffset, op, kind, prediction)) {
1312             if (UNLIKELY(m_graph.compilation()))
1313                 m_graph.compilation()->noticeInlinedCall();
1314             return NonTerminal;
1315         }
1316     }
1317     
1318     Node* callNode = addCall(result, op, nullptr, callTarget, argumentCountIncludingThis, registerOffset, prediction);
1319     ASSERT(callNode->op() != TailCallVarargs && callNode->op() != TailCallForwardVarargs);
1320     return callNode->op() == TailCall ? Terminal : NonTerminal;
1321 }
1322
1323 ByteCodeParser::Terminality ByteCodeParser::handleVarargsCall(Instruction* pc, NodeType op, CallMode callMode)
1324 {
1325     static_assert(OPCODE_LENGTH(op_call_varargs) == OPCODE_LENGTH(op_construct_varargs),
1326         "op_call_varargs, op_tail_call_varargs and op_construct_varargs should always have the same length");
1327     static_assert(OPCODE_LENGTH(op_call_varargs) == OPCODE_LENGTH(op_tail_call_varargs),
1328         "op_call_varargs, op_tail_call_varargs and op_construct_varargs should always have the same length");
1329
1330     int result = pc[1].u.operand;
1331     int callee = pc[2].u.operand;
1332     int thisReg = pc[3].u.operand;
1333     int arguments = pc[4].u.operand;
1334     int firstFreeReg = pc[5].u.operand;
1335     int firstVarArgOffset = pc[6].u.operand;
1336     
1337     SpeculatedType prediction = getPrediction();
1338     
1339     Node* callTarget = get(VirtualRegister(callee));
1340     
1341     CallLinkStatus callLinkStatus = CallLinkStatus::computeFor(
1342         m_inlineStackTop->m_profiledBlock, currentCodeOrigin(),
1343         m_inlineStackTop->m_callLinkInfos, m_callContextMap);
1344     refineStatically(callLinkStatus, callTarget);
1345     
1346     VERBOSE_LOG("    Varargs call link status at ", currentCodeOrigin(), ": ", callLinkStatus, "\n");
1347     
1348     if (callLinkStatus.canOptimize()
1349         && handleInlining(callTarget, result, callLinkStatus, firstFreeReg, VirtualRegister(thisReg), VirtualRegister(arguments), firstVarArgOffset, 0, m_currentIndex + OPCODE_LENGTH(op_call_varargs), op, InlineCallFrame::varargsKindFor(callMode), prediction)) {
1350         if (UNLIKELY(m_graph.compilation()))
1351             m_graph.compilation()->noticeInlinedCall();
1352         return NonTerminal;
1353     }
1354     
1355     CallVarargsData* data = m_graph.m_callVarargsData.add();
1356     data->firstVarArgOffset = firstVarArgOffset;
1357     
1358     Node* thisChild = get(VirtualRegister(thisReg));
1359     Node* argumentsChild = nullptr;
1360     if (op != TailCallForwardVarargs)
1361         argumentsChild = get(VirtualRegister(arguments));
1362
1363     if (op == TailCallVarargs || op == TailCallForwardVarargs) {
1364         if (allInlineFramesAreTailCalls()) {
1365             addToGraph(op, OpInfo(data), OpInfo(), callTarget, thisChild, argumentsChild);
1366             return Terminal;
1367         }
1368         op = op == TailCallVarargs ? TailCallVarargsInlinedCaller : TailCallForwardVarargsInlinedCaller;
1369     }
1370
1371     Node* call = addToGraph(op, OpInfo(data), OpInfo(prediction), callTarget, thisChild, argumentsChild);
1372     VirtualRegister resultReg(result);
1373     if (resultReg.isValid())
1374         set(resultReg, call);
1375     return NonTerminal;
1376 }
1377
1378 void ByteCodeParser::emitFunctionChecks(CallVariant callee, Node* callTarget, VirtualRegister thisArgumentReg)
1379 {
1380     Node* thisArgument;
1381     if (thisArgumentReg.isValid())
1382         thisArgument = get(thisArgumentReg);
1383     else
1384         thisArgument = nullptr;
1385
1386     JSCell* calleeCell;
1387     Node* callTargetForCheck;
1388     if (callee.isClosureCall()) {
1389         calleeCell = callee.executable();
1390         callTargetForCheck = addToGraph(GetExecutable, callTarget);
1391     } else {
1392         calleeCell = callee.nonExecutableCallee();
1393         callTargetForCheck = callTarget;
1394     }
1395     
1396     ASSERT(calleeCell);
1397     addToGraph(CheckCell, OpInfo(m_graph.freeze(calleeCell)), callTargetForCheck);
1398     if (thisArgument)
1399         addToGraph(Phantom, thisArgument);
1400 }
1401
1402 Node* ByteCodeParser::getArgumentCount()
1403 {
1404     Node* argumentCount;
1405     if (m_inlineStackTop->m_inlineCallFrame) {
1406         if (m_inlineStackTop->m_inlineCallFrame->isVarargs())
1407             argumentCount = get(VirtualRegister(CallFrameSlot::argumentCount));
1408         else
1409             argumentCount = jsConstant(m_graph.freeze(jsNumber(m_inlineStackTop->m_inlineCallFrame->argumentCountIncludingThis))->value());
1410     } else
1411         argumentCount = addToGraph(GetArgumentCountIncludingThis, OpInfo(0), OpInfo(SpecInt32Only));
1412     return argumentCount;
1413 }
1414
1415 void ByteCodeParser::emitArgumentPhantoms(int registerOffset, int argumentCountIncludingThis)
1416 {
1417     for (int i = 0; i < argumentCountIncludingThis; ++i)
1418         addToGraph(Phantom, get(virtualRegisterForArgument(i, registerOffset)));
1419 }
1420
1421 bool ByteCodeParser::handleRecursiveTailCall(Node* callTargetNode, const CallLinkStatus& callLinkStatus, int registerOffset, VirtualRegister thisArgument, int argumentCountIncludingThis)
1422 {
1423     // FIXME: We currently only do this optimisation in the simple, non-polymorphic case.
1424     // https://bugs.webkit.org/show_bug.cgi?id=178390
1425     if (callLinkStatus.couldTakeSlowPath() || callLinkStatus.size() != 1)
1426         return false;
1427
1428     auto targetExecutable = callLinkStatus[0].executable();
1429     InlineStackEntry* stackEntry = m_inlineStackTop;
1430     do {
1431         if (targetExecutable != stackEntry->executable())
1432             continue;
1433         VERBOSE_LOG("   We found a recursive tail call, trying to optimize it into a jump.\n");
1434
1435         if (auto* callFrame = stackEntry->m_inlineCallFrame) {
1436             // Some code may statically use the argument count from the InlineCallFrame, so it would be invalid to loop back if it does not match.
1437             // We "continue" instead of returning false in case another stack entry further on the stack has the right number of arguments.
1438             if (argumentCountIncludingThis != static_cast<int>(callFrame->argumentCountIncludingThis))
1439                 continue;
1440         } else {
1441             // We are in the machine code entry (i.e. the original caller).
1442             // If we have more arguments than the number of parameters to the function, it is not clear where we could put them on the stack.
1443             if (argumentCountIncludingThis > m_codeBlock->numParameters())
1444                 return false;
1445         }
1446
1447         // We must add some check that the profiling information was correct and the target of this call is what we thought
1448         emitFunctionChecks(callLinkStatus[0], callTargetNode, thisArgument);
1449         // We flush everything, as if we were in the backedge of a loop (see treatment of op_jmp in parseBlock).
1450         flushForTerminal();
1451
1452         // We must set the arguments to the right values
1453         int argIndex = 0;
1454         for (; argIndex < argumentCountIncludingThis; ++argIndex) {
1455             Node* value = get(virtualRegisterForArgument(argIndex, registerOffset));
1456             setDirect(stackEntry->remapOperand(virtualRegisterForArgument(argIndex)), value, NormalSet);
1457         }
1458         Node* undefined = addToGraph(JSConstant, OpInfo(m_constantUndefined));
1459         for (; argIndex < stackEntry->m_codeBlock->numParameters(); ++argIndex)
1460             setDirect(stackEntry->remapOperand(virtualRegisterForArgument(argIndex)), undefined, NormalSet);
1461
1462         // We must repeat the work of op_enter here as we will jump right after it.
1463         // We jump right after it and not before it, because of some invariant saying that a CFG root cannot have predecessors in the IR.
1464         for (int i = 0; i < stackEntry->m_codeBlock->m_numVars; ++i)
1465             setDirect(stackEntry->remapOperand(virtualRegisterForLocal(i)), undefined, NormalSet);
1466
1467         // We want to emit the SetLocals with an exit origin that points to the place we are jumping to.
1468         unsigned oldIndex = m_currentIndex;
1469         auto oldStackTop = m_inlineStackTop;
1470         m_inlineStackTop = stackEntry;
1471         m_currentIndex = OPCODE_LENGTH(op_enter);
1472         m_exitOK = true;
1473         processSetLocalQueue();
1474         m_currentIndex = oldIndex;
1475         m_inlineStackTop = oldStackTop;
1476         m_exitOK = false;
1477
1478         BasicBlock** entryBlockPtr = tryBinarySearch<BasicBlock*, unsigned>(stackEntry->m_blockLinkingTargets, stackEntry->m_blockLinkingTargets.size(), OPCODE_LENGTH(op_enter), getBytecodeBeginForBlock);
1479         RELEASE_ASSERT(entryBlockPtr);
1480         addJumpTo(*entryBlockPtr);
1481         return true;
1482         // It would be unsound to jump over a non-tail call: the "tail" call is not really a tail call in that case.
1483     } while (stackEntry->m_inlineCallFrame && stackEntry->m_inlineCallFrame->kind == InlineCallFrame::TailCall && (stackEntry = stackEntry->m_caller));
1484
1485     // The tail call was not recursive
1486     return false;
1487 }
1488
1489 unsigned ByteCodeParser::inliningCost(CallVariant callee, int argumentCountIncludingThis, InlineCallFrame::Kind kind)
1490 {
1491     CallMode callMode = InlineCallFrame::callModeFor(kind);
1492     CodeSpecializationKind specializationKind = specializationKindFor(callMode);
1493     VERBOSE_LOG("Considering inlining ", callee, " into ", currentCodeOrigin(), "\n");
1494     
1495     if (m_hasDebuggerEnabled) {
1496         VERBOSE_LOG("    Failing because the debugger is in use.\n");
1497         return UINT_MAX;
1498     }
1499
1500     FunctionExecutable* executable = callee.functionExecutable();
1501     if (!executable) {
1502         VERBOSE_LOG("    Failing because there is no function executable.\n");
1503         return UINT_MAX;
1504     }
1505     
1506     // Do we have a code block, and does the code block's size match the heuristics/requirements for
1507     // being an inline candidate? We might not have a code block (1) if code was thrown away,
1508     // (2) if we simply hadn't actually made this call yet or (3) code is a builtin function and
1509     // specialization kind is construct. In the former 2 cases, we could still theoretically attempt
1510     // to inline it if we had a static proof of what was being called; this might happen for example
1511     // if you call a global function, where watchpointing gives us static information. Overall,
1512     // it's a rare case because we expect that any hot callees would have already been compiled.
1513     CodeBlock* codeBlock = executable->baselineCodeBlockFor(specializationKind);
1514     if (!codeBlock) {
1515         VERBOSE_LOG("    Failing because no code block available.\n");
1516         return UINT_MAX;
1517     }
1518
1519     if (!Options::useArityFixupInlining()) {
1520         if (codeBlock->numParameters() > argumentCountIncludingThis) {
1521             VERBOSE_LOG("    Failing because of arity mismatch.\n");
1522             return UINT_MAX;
1523         }
1524     }
1525
1526     CapabilityLevel capabilityLevel = inlineFunctionForCapabilityLevel(
1527         codeBlock, specializationKind, callee.isClosureCall());
1528     VERBOSE_LOG("    Call mode: ", callMode, "\n");
1529     VERBOSE_LOG("    Is closure call: ", callee.isClosureCall(), "\n");
1530     VERBOSE_LOG("    Capability level: ", capabilityLevel, "\n");
1531     VERBOSE_LOG("    Might inline function: ", mightInlineFunctionFor(codeBlock, specializationKind), "\n");
1532     VERBOSE_LOG("    Might compile function: ", mightCompileFunctionFor(codeBlock, specializationKind), "\n");
1533     VERBOSE_LOG("    Is supported for inlining: ", isSupportedForInlining(codeBlock), "\n");
1534     VERBOSE_LOG("    Is inlining candidate: ", codeBlock->ownerScriptExecutable()->isInliningCandidate(), "\n");
1535     if (!canInline(capabilityLevel)) {
1536         VERBOSE_LOG("    Failing because the function is not inlineable.\n");
1537         return UINT_MAX;
1538     }
1539     
1540     // Check if the caller is already too large. We do this check here because that's just
1541     // where we happen to also have the callee's code block, and we want that for the
1542     // purpose of unsetting SABI.
1543     if (!isSmallEnoughToInlineCodeInto(m_codeBlock)) {
1544         codeBlock->m_shouldAlwaysBeInlined = false;
1545         VERBOSE_LOG("    Failing because the caller is too large.\n");
1546         return UINT_MAX;
1547     }
1548     
1549     // FIXME: this should be better at predicting how much bloat we will introduce by inlining
1550     // this function.
1551     // https://bugs.webkit.org/show_bug.cgi?id=127627
1552     
1553     // FIXME: We currently inline functions that have run in LLInt but not in Baseline. These
1554     // functions have very low fidelity profiling, and presumably they weren't very hot if they
1555     // haven't gotten to Baseline yet. Consider not inlining these functions.
1556     // https://bugs.webkit.org/show_bug.cgi?id=145503
1557     
1558     // Have we exceeded inline stack depth, or are we trying to inline a recursive call to
1559     // too many levels? If either of these are detected, then don't inline. We adjust our
1560     // heuristics if we are dealing with a function that cannot otherwise be compiled.
1561     
1562     unsigned depth = 0;
1563     unsigned recursion = 0;
1564     
1565     for (InlineStackEntry* entry = m_inlineStackTop; entry; entry = entry->m_caller) {
1566         ++depth;
1567         if (depth >= Options::maximumInliningDepth()) {
1568             VERBOSE_LOG("    Failing because depth exceeded.\n");
1569             return UINT_MAX;
1570         }
1571         
1572         if (entry->executable() == executable) {
1573             ++recursion;
1574             if (recursion >= Options::maximumInliningRecursion()) {
1575                 VERBOSE_LOG("    Failing because recursion detected.\n");
1576                 return UINT_MAX;
1577             }
1578         }
1579     }
1580     
1581     VERBOSE_LOG("    Inlining should be possible.\n");
1582     
1583     // It might be possible to inline.
1584     return codeBlock->instructionCount();
1585 }
1586
1587 template<typename ChecksFunctor>
1588 void ByteCodeParser::inlineCall(Node* callTargetNode, int resultOperand, CallVariant callee, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, InlineCallFrame::Kind kind, BasicBlock* continuationBlock, const ChecksFunctor& insertChecks)
1589 {
1590     CodeSpecializationKind specializationKind = InlineCallFrame::specializationKindFor(kind);
1591     
1592     ASSERT(inliningCost(callee, argumentCountIncludingThis, kind) != UINT_MAX);
1593     
1594     CodeBlock* codeBlock = callee.functionExecutable()->baselineCodeBlockFor(specializationKind);
1595     insertChecks(codeBlock);
1596
1597     // FIXME: Don't flush constants!
1598
1599     // arityFixupCount and numberOfStackPaddingSlots are different. While arityFixupCount does not consider about stack alignment,
1600     // numberOfStackPaddingSlots consider alignment. Consider the following case,
1601     //
1602     // before: [ ... ][arg0][header]
1603     // after:  [ ... ][ext ][arg1][arg0][header]
1604     //
1605     // In the above case, arityFixupCount is 1. But numberOfStackPaddingSlots is 2 because the stack needs to be aligned.
1606     // We insert extra slots to align stack.
1607     int arityFixupCount = std::max<int>(codeBlock->numParameters() - argumentCountIncludingThis, 0);
1608     int numberOfStackPaddingSlots = CommonSlowPaths::numberOfStackPaddingSlots(codeBlock, argumentCountIncludingThis);
1609     ASSERT(!(numberOfStackPaddingSlots % stackAlignmentRegisters()));
1610     int registerOffsetAfterFixup = registerOffset - numberOfStackPaddingSlots;
1611     
1612     int inlineCallFrameStart = m_inlineStackTop->remapOperand(VirtualRegister(registerOffsetAfterFixup)).offset() + CallFrame::headerSizeInRegisters;
1613     
1614     ensureLocals(
1615         VirtualRegister(inlineCallFrameStart).toLocal() + 1 +
1616         CallFrame::headerSizeInRegisters + codeBlock->m_numCalleeLocals);
1617     
1618     size_t argumentPositionStart = m_graph.m_argumentPositions.size();
1619
1620     VirtualRegister resultReg(resultOperand);
1621     if (resultReg.isValid())
1622         resultReg = m_inlineStackTop->remapOperand(resultReg);
1623
1624     VariableAccessData* calleeVariable = nullptr;
1625     if (callee.isClosureCall()) {
1626         Node* calleeSet = set(
1627             VirtualRegister(registerOffsetAfterFixup + CallFrameSlot::callee), callTargetNode, ImmediateNakedSet);
1628         
1629         calleeVariable = calleeSet->variableAccessData();
1630         calleeVariable->mergeShouldNeverUnbox(true);
1631     }
1632
1633     if (arityFixupCount) {
1634         // Note: we do arity fixup in two phases:
1635         // 1. We get all the values we need and MovHint them to the expected locals.
1636         // 2. We SetLocal them inside the callee's CodeOrigin. This way, if we exit, the callee's
1637         //    frame is already set up. If any SetLocal exits, we have a valid exit state.
1638         //    This is required because if we didn't do this in two phases, we may exit in
1639         //    the middle of arity fixup from the caller's CodeOrigin. This is unsound because if
1640         //    we did the SetLocals in the caller's frame, the memcpy may clobber needed parts
1641         //    of the frame right before exiting. For example, consider if we need to pad two args:
1642         //    [arg3][arg2][arg1][arg0]
1643         //    [fix ][fix ][arg3][arg2][arg1][arg0]
1644         //    We memcpy starting from arg0 in the direction of arg3. If we were to exit at a type check
1645         //    for arg3's SetLocal in the caller's CodeOrigin, we'd exit with a frame like so:
1646         //    [arg3][arg2][arg1][arg2][arg1][arg0]
1647         //    And the caller would then just end up thinking its argument are:
1648         //    [arg3][arg2][arg1][arg2]
1649         //    which is incorrect.
1650
1651         Node* undefined = addToGraph(JSConstant, OpInfo(m_constantUndefined));
1652         // The stack needs to be aligned due to the JS calling convention. Thus, we have a hole if the count of arguments is not aligned.
1653         // We call this hole "extra slot". Consider the following case, the number of arguments is 2. If this argument
1654         // count does not fulfill the stack alignment requirement, we already inserted extra slots.
1655         //
1656         // before: [ ... ][ext ][arg1][arg0][header]
1657         //
1658         // In the above case, one extra slot is inserted. If the code's parameter count is 3, we will fixup arguments.
1659         // At that time, we can simply use this extra slots. So the fixuped stack is the following.
1660         //
1661         // before: [ ... ][ext ][arg1][arg0][header]
1662         // after:  [ ... ][arg2][arg1][arg0][header]
1663         //
1664         // In such cases, we do not need to move frames.
1665         if (registerOffsetAfterFixup != registerOffset) {
1666             for (int index = 0; index < argumentCountIncludingThis; ++index) {
1667                 Node* value = get(virtualRegisterForArgument(index, registerOffset));
1668                 VirtualRegister argumentToSet = m_inlineStackTop->remapOperand(virtualRegisterForArgument(index, registerOffsetAfterFixup));
1669                 addToGraph(MovHint, OpInfo(argumentToSet.offset()), value);
1670                 m_setLocalQueue.append(DelayedSetLocal { currentCodeOrigin(), argumentToSet, value, ImmediateNakedSet });
1671             }
1672         }
1673         for (int index = 0; index < arityFixupCount; ++index) {
1674             VirtualRegister argumentToSet = m_inlineStackTop->remapOperand(virtualRegisterForArgument(argumentCountIncludingThis + index, registerOffsetAfterFixup));
1675             addToGraph(MovHint, OpInfo(argumentToSet.offset()), undefined);
1676             m_setLocalQueue.append(DelayedSetLocal { currentCodeOrigin(), argumentToSet, undefined, ImmediateNakedSet });
1677         }
1678
1679         // At this point, it's OK to OSR exit because we finished setting up
1680         // our callee's frame. We emit an ExitOK below from the callee's CodeOrigin.
1681     }
1682
1683     InlineStackEntry inlineStackEntry(this, codeBlock, codeBlock, callee.function(), resultReg,
1684         (VirtualRegister)inlineCallFrameStart, argumentCountIncludingThis, kind, continuationBlock);
1685
1686     // This is where the actual inlining really happens.
1687     unsigned oldIndex = m_currentIndex;
1688     m_currentIndex = 0;
1689
1690     // At this point, it's again OK to OSR exit.
1691     m_exitOK = true;
1692     addToGraph(ExitOK);
1693
1694     processSetLocalQueue();
1695
1696     InlineVariableData inlineVariableData;
1697     inlineVariableData.inlineCallFrame = m_inlineStackTop->m_inlineCallFrame;
1698     inlineVariableData.argumentPositionStart = argumentPositionStart;
1699     inlineVariableData.calleeVariable = 0;
1700     
1701     RELEASE_ASSERT(
1702         m_inlineStackTop->m_inlineCallFrame->isClosureCall
1703         == callee.isClosureCall());
1704     if (callee.isClosureCall()) {
1705         RELEASE_ASSERT(calleeVariable);
1706         inlineVariableData.calleeVariable = calleeVariable;
1707     }
1708     
1709     m_graph.m_inlineVariableData.append(inlineVariableData);
1710
1711     parseCodeBlock();
1712     clearCaches(); // Reset our state now that we're back to the outer code.
1713     
1714     m_currentIndex = oldIndex;
1715     m_exitOK = false;
1716
1717     linkBlocks(inlineStackEntry.m_unlinkedBlocks, inlineStackEntry.m_blockLinkingTargets);
1718     
1719     // If the callee returned at least once, it prepared a continuation block for us.
1720     if (inlineStackEntry.m_continuationBlock)
1721         m_currentBlock = inlineStackEntry.m_continuationBlock;
1722     else {
1723         // We are in the case where the callee never returns (for example it loops forever).
1724         // In that case, all blocks should end in a terminal.
1725         ASSERT(m_graph.lastBlock()->terminal());
1726         // We then allocate a new block to continue in.
1727         m_currentBlock = allocateTargetableBlock(nextOffset);
1728     }
1729     ASSERT(m_currentBlock);
1730     ASSERT(!m_currentBlock->terminal());
1731
1732     prepareToParseBlock();
1733 }
1734
1735 template<typename ChecksFunctor>
1736 bool ByteCodeParser::attemptToInlineCall(Node* callTargetNode, int resultOperand, CallVariant callee, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, InlineCallFrame::Kind kind, SpeculatedType prediction, unsigned& inliningBalance, BasicBlock* continuationBlock, const ChecksFunctor& insertChecks)
1737 {
1738     CodeSpecializationKind specializationKind = InlineCallFrame::specializationKindFor(kind);
1739     
1740     if (!inliningBalance)
1741         return false;
1742     
1743     VERBOSE_LOG("    Considering callee ", callee, "\n");
1744     
1745     // Intrinsics and internal functions can only be inlined if we're not doing varargs. This is because
1746     // we currently don't have any way of getting profiling information for arguments to non-JS varargs
1747     // calls. The prediction propagator won't be of any help because LoadVarargs obscures the data flow,
1748     // and there are no callsite value profiles and native function won't have callee value profiles for
1749     // those arguments. Even worse, if the intrinsic decides to exit, it won't really have anywhere to
1750     // exit to: LoadVarargs is effectful and it's part of the op_call_varargs, so we can't exit without
1751     // calling LoadVarargs twice.
1752     if (!InlineCallFrame::isVarargs(kind)) {
1753
1754         bool didInsertChecks = false;
1755         auto insertChecksWithAccounting = [&] () {
1756             insertChecks(nullptr);
1757             didInsertChecks = true;
1758         };
1759
1760         auto endSpecialCase = [&] () {
1761             RELEASE_ASSERT(didInsertChecks);
1762             addToGraph(Phantom, callTargetNode);
1763             emitArgumentPhantoms(registerOffset, argumentCountIncludingThis);
1764             inliningBalance--;
1765             if (continuationBlock) {
1766                 m_currentIndex = nextOffset;
1767                 m_exitOK = true;
1768                 processSetLocalQueue();
1769                 addJumpTo(continuationBlock);
1770             }
1771         };
1772     
1773         if (InternalFunction* function = callee.internalFunction()) {
1774             if (handleConstantInternalFunction(callTargetNode, resultOperand, function, registerOffset, argumentCountIncludingThis, specializationKind, prediction, insertChecksWithAccounting)) {
1775                 endSpecialCase();
1776                 return true;
1777             }
1778             RELEASE_ASSERT(!didInsertChecks);
1779             return false;
1780         }
1781     
1782         Intrinsic intrinsic = callee.intrinsicFor(specializationKind);
1783         if (intrinsic != NoIntrinsic) {
1784             if (handleIntrinsicCall(callTargetNode, resultOperand, intrinsic, registerOffset, argumentCountIncludingThis, prediction, insertChecksWithAccounting)) {
1785                 endSpecialCase();
1786                 return true;
1787             }
1788
1789             RELEASE_ASSERT(!didInsertChecks);
1790             // We might still try to inline the Intrinsic because it might be a builtin JS function.
1791         }
1792
1793         if (Options::useDOMJIT()) {
1794             if (const DOMJIT::Signature* signature = callee.signatureFor(specializationKind)) {
1795                 if (handleDOMJITCall(callTargetNode, resultOperand, signature, registerOffset, argumentCountIncludingThis, prediction, insertChecksWithAccounting)) {
1796                     endSpecialCase();
1797                     return true;
1798                 }
1799                 RELEASE_ASSERT(!didInsertChecks);
1800             }
1801         }
1802     }
1803     
1804     unsigned myInliningCost = inliningCost(callee, argumentCountIncludingThis, kind);
1805     if (myInliningCost > inliningBalance)
1806         return false;
1807
1808     Instruction* savedCurrentInstruction = m_currentInstruction;
1809     inlineCall(callTargetNode, resultOperand, callee, registerOffset, argumentCountIncludingThis, nextOffset, kind, continuationBlock, insertChecks);
1810     inliningBalance -= myInliningCost;
1811     m_currentInstruction = savedCurrentInstruction;
1812     return true;
1813 }
1814
1815 bool ByteCodeParser::handleInlining(
1816     Node* callTargetNode, int resultOperand, const CallLinkStatus& callLinkStatus,
1817     int registerOffsetOrFirstFreeReg, VirtualRegister thisArgument,
1818     VirtualRegister argumentsArgument, unsigned argumentsOffset, int argumentCountIncludingThis,
1819     unsigned nextOffset, NodeType callOp, InlineCallFrame::Kind kind, SpeculatedType prediction)
1820 {
1821     VERBOSE_LOG("Handling inlining...\nStack: ", currentCodeOrigin(), "\n");
1822     CodeSpecializationKind specializationKind = InlineCallFrame::specializationKindFor(kind);
1823     
1824     if (!callLinkStatus.size()) {
1825         VERBOSE_LOG("Bailing inlining.\n");
1826         return false;
1827     }
1828     
1829     if (InlineCallFrame::isVarargs(kind)
1830         && callLinkStatus.maxNumArguments() > Options::maximumVarargsForInlining()) {
1831         VERBOSE_LOG("Bailing inlining because of varargs.\n");
1832         return false;
1833     }
1834         
1835     unsigned inliningBalance = Options::maximumFunctionForCallInlineCandidateInstructionCount();
1836     if (specializationKind == CodeForConstruct)
1837         inliningBalance = std::min(inliningBalance, Options::maximumFunctionForConstructInlineCandidateInstructionCount());
1838     if (callLinkStatus.isClosureCall())
1839         inliningBalance = std::min(inliningBalance, Options::maximumFunctionForClosureCallInlineCandidateInstructionCount());
1840     
1841     // First check if we can avoid creating control flow. Our inliner does some CFG
1842     // simplification on the fly and this helps reduce compile times, but we can only leverage
1843     // this in cases where we don't need control flow diamonds to check the callee.
1844     if (!callLinkStatus.couldTakeSlowPath() && callLinkStatus.size() == 1) {
1845         int registerOffset;
1846         
1847         // Only used for varargs calls.
1848         unsigned mandatoryMinimum = 0;
1849         unsigned maxNumArguments = 0;
1850
1851         if (InlineCallFrame::isVarargs(kind)) {
1852             if (FunctionExecutable* functionExecutable = callLinkStatus[0].functionExecutable())
1853                 mandatoryMinimum = functionExecutable->parameterCount();
1854             else
1855                 mandatoryMinimum = 0;
1856             
1857             // includes "this"
1858             maxNumArguments = std::max(
1859                 callLinkStatus.maxNumArguments(),
1860                 mandatoryMinimum + 1);
1861             
1862             // We sort of pretend that this *is* the number of arguments that were passed.
1863             argumentCountIncludingThis = maxNumArguments;
1864             
1865             registerOffset = registerOffsetOrFirstFreeReg + 1;
1866             registerOffset -= maxNumArguments; // includes "this"
1867             registerOffset -= CallFrame::headerSizeInRegisters;
1868             registerOffset = -WTF::roundUpToMultipleOf(
1869                 stackAlignmentRegisters(),
1870                 -registerOffset);
1871         } else
1872             registerOffset = registerOffsetOrFirstFreeReg;
1873         
1874         bool result = attemptToInlineCall(
1875             callTargetNode, resultOperand, callLinkStatus[0], registerOffset,
1876             argumentCountIncludingThis, nextOffset, kind, prediction,
1877             inliningBalance, nullptr, [&] (CodeBlock* codeBlock) {
1878                 emitFunctionChecks(callLinkStatus[0], callTargetNode, thisArgument);
1879
1880                 // If we have a varargs call, we want to extract the arguments right now.
1881                 if (InlineCallFrame::isVarargs(kind)) {
1882                     int remappedRegisterOffset =
1883                         m_inlineStackTop->remapOperand(VirtualRegister(registerOffset)).offset();
1884                     
1885                     ensureLocals(VirtualRegister(remappedRegisterOffset).toLocal());
1886                     
1887                     int argumentStart = registerOffset + CallFrame::headerSizeInRegisters;
1888                     int remappedArgumentStart =
1889                         m_inlineStackTop->remapOperand(VirtualRegister(argumentStart)).offset();
1890
1891                     LoadVarargsData* data = m_graph.m_loadVarargsData.add();
1892                     data->start = VirtualRegister(remappedArgumentStart + 1);
1893                     data->count = VirtualRegister(remappedRegisterOffset + CallFrameSlot::argumentCount);
1894                     data->offset = argumentsOffset;
1895                     data->limit = maxNumArguments;
1896                     data->mandatoryMinimum = mandatoryMinimum;
1897
1898                     if (callOp == TailCallForwardVarargs)
1899                         addToGraph(ForwardVarargs, OpInfo(data));
1900                     else
1901                         addToGraph(LoadVarargs, OpInfo(data), get(argumentsArgument));
1902
1903                     // LoadVarargs may OSR exit. Hence, we need to keep alive callTargetNode, thisArgument
1904                     // and argumentsArgument for the baseline JIT. However, we only need a Phantom for
1905                     // callTargetNode because the other 2 are still in use and alive at this point.
1906                     addToGraph(Phantom, callTargetNode);
1907
1908                     // In DFG IR before SSA, we cannot insert control flow between after the
1909                     // LoadVarargs and the last SetArgument. This isn't a problem once we get to DFG
1910                     // SSA. Fortunately, we also have other reasons for not inserting control flow
1911                     // before SSA.
1912             
1913                     VariableAccessData* countVariable = newVariableAccessData(
1914                         VirtualRegister(remappedRegisterOffset + CallFrameSlot::argumentCount));
1915                     // This is pretty lame, but it will force the count to be flushed as an int. This doesn't
1916                     // matter very much, since our use of a SetArgument and Flushes for this local slot is
1917                     // mostly just a formality.
1918                     countVariable->predict(SpecInt32Only);
1919                     countVariable->mergeIsProfitableToUnbox(true);
1920                     Node* setArgumentCount = addToGraph(SetArgument, OpInfo(countVariable));
1921                     m_currentBlock->variablesAtTail.setOperand(countVariable->local(), setArgumentCount);
1922
1923                     set(VirtualRegister(argumentStart), get(thisArgument), ImmediateNakedSet);
1924                     for (unsigned argument = 1; argument < maxNumArguments; ++argument) {
1925                         VariableAccessData* variable = newVariableAccessData(
1926                             VirtualRegister(remappedArgumentStart + argument));
1927                         variable->mergeShouldNeverUnbox(true); // We currently have nowhere to put the type check on the LoadVarargs. LoadVarargs is effectful, so after it finishes, we cannot exit.
1928                         
1929                         // For a while it had been my intention to do things like this inside the
1930                         // prediction injection phase. But in this case it's really best to do it here,
1931                         // because it's here that we have access to the variable access datas for the
1932                         // inlining we're about to do.
1933                         //
1934                         // Something else that's interesting here is that we'd really love to get
1935                         // predictions from the arguments loaded at the callsite, rather than the
1936                         // arguments received inside the callee. But that probably won't matter for most
1937                         // calls.
1938                         if (codeBlock && argument < static_cast<unsigned>(codeBlock->numParameters())) {
1939                             ConcurrentJSLocker locker(codeBlock->m_lock);
1940                             ValueProfile& profile = codeBlock->valueProfileForArgument(argument);
1941                             variable->predict(profile.computeUpdatedPrediction(locker));
1942                         }
1943                         
1944                         Node* setArgument = addToGraph(SetArgument, OpInfo(variable));
1945                         m_currentBlock->variablesAtTail.setOperand(variable->local(), setArgument);
1946                     }
1947                 }
1948             });
1949         VERBOSE_LOG("Done inlining (simple).\nStack: ", currentCodeOrigin(), "\nResult: ", result, "\n");
1950         return result;
1951     }
1952     
1953     // We need to create some kind of switch over callee. For now we only do this if we believe that
1954     // we're in the top tier. We have two reasons for this: first, it provides us an opportunity to
1955     // do more detailed polyvariant/polymorphic profiling; and second, it reduces compile times in
1956     // the DFG. And by polyvariant profiling we mean polyvariant profiling of *this* call. Note that
1957     // we could improve that aspect of this by doing polymorphic inlining but having the profiling
1958     // also.
1959     if (!isFTL(m_graph.m_plan.mode) || !Options::usePolymorphicCallInlining()
1960         || InlineCallFrame::isVarargs(kind)) {
1961         VERBOSE_LOG("Bailing inlining (hard).\nStack: ", currentCodeOrigin(), "\n");
1962         return false;
1963     }
1964     
1965     // If the claim is that this did not originate from a stub, then we don't want to emit a switch
1966     // statement. Whenever the non-stub profiling says that it could take slow path, it really means that
1967     // it has no idea.
1968     if (!Options::usePolymorphicCallInliningForNonStubStatus()
1969         && !callLinkStatus.isBasedOnStub()) {
1970         VERBOSE_LOG("Bailing inlining (non-stub polymorphism).\nStack: ", currentCodeOrigin(), "\n");
1971         return false;
1972     }
1973
1974     bool allAreClosureCalls = true;
1975     bool allAreDirectCalls = true;
1976     for (unsigned i = callLinkStatus.size(); i--;) {
1977         if (callLinkStatus[i].isClosureCall())
1978             allAreDirectCalls = false;
1979         else
1980             allAreClosureCalls = false;
1981     }
1982
1983     Node* thingToSwitchOn;
1984     if (allAreDirectCalls)
1985         thingToSwitchOn = callTargetNode;
1986     else if (allAreClosureCalls)
1987         thingToSwitchOn = addToGraph(GetExecutable, callTargetNode);
1988     else {
1989         // FIXME: We should be able to handle this case, but it's tricky and we don't know of cases
1990         // where it would be beneficial. It might be best to handle these cases as if all calls were
1991         // closure calls.
1992         // https://bugs.webkit.org/show_bug.cgi?id=136020
1993         VERBOSE_LOG("Bailing inlining (mix).\nStack: ", currentCodeOrigin(), "\n");
1994         return false;
1995     }
1996
1997     VERBOSE_LOG("Doing hard inlining...\nStack: ", currentCodeOrigin(), "\n");
1998
1999     int registerOffset = registerOffsetOrFirstFreeReg;
2000
2001     // This makes me wish that we were in SSA all the time. We need to pick a variable into which to
2002     // store the callee so that it will be accessible to all of the blocks we're about to create. We
2003     // get away with doing an immediate-set here because we wouldn't have performed any side effects
2004     // yet.
2005     VERBOSE_LOG("Register offset: ", registerOffset);
2006     VirtualRegister calleeReg(registerOffset + CallFrameSlot::callee);
2007     calleeReg = m_inlineStackTop->remapOperand(calleeReg);
2008     VERBOSE_LOG("Callee is going to be ", calleeReg, "\n");
2009     setDirect(calleeReg, callTargetNode, ImmediateSetWithFlush);
2010
2011     // It's OK to exit right now, even though we set some locals. That's because those locals are not
2012     // user-visible.
2013     m_exitOK = true;
2014     addToGraph(ExitOK);
2015     
2016     SwitchData& data = *m_graph.m_switchData.add();
2017     data.kind = SwitchCell;
2018     addToGraph(Switch, OpInfo(&data), thingToSwitchOn);
2019     m_currentBlock->didLink();
2020     
2021     BasicBlock* continuationBlock = allocateUntargetableBlock();
2022     VERBOSE_LOG("Adding untargetable block ", RawPointer(continuationBlock), " (continuation)\n");
2023     
2024     // We may force this true if we give up on inlining any of the edges.
2025     bool couldTakeSlowPath = callLinkStatus.couldTakeSlowPath();
2026     
2027     VERBOSE_LOG("About to loop over functions at ", currentCodeOrigin(), ".\n");
2028
2029     unsigned oldOffset = m_currentIndex;
2030     for (unsigned i = 0; i < callLinkStatus.size(); ++i) {
2031         m_currentIndex = oldOffset;
2032         BasicBlock* calleeEntryBlock = allocateUntargetableBlock();
2033         m_currentBlock = calleeEntryBlock;
2034         prepareToParseBlock();
2035         
2036         Node* myCallTargetNode = getDirect(calleeReg);
2037         
2038         bool inliningResult = attemptToInlineCall(
2039             myCallTargetNode, resultOperand, callLinkStatus[i], registerOffset,
2040             argumentCountIncludingThis, nextOffset, kind, prediction,
2041             inliningBalance, continuationBlock, [&] (CodeBlock*) { });
2042         
2043         if (!inliningResult) {
2044             // That failed so we let the block die. Nothing interesting should have been added to
2045             // the block. We also give up on inlining any of the (less frequent) callees.
2046             ASSERT(m_graph.m_blocks.last() == m_currentBlock);
2047             m_graph.killBlockAndItsContents(m_currentBlock);
2048             m_graph.m_blocks.removeLast();
2049             VERBOSE_LOG("Inlining of a poly call failed, we will have to go through a slow path\n");
2050
2051             // The fact that inlining failed means we need a slow path.
2052             couldTakeSlowPath = true;
2053             break;
2054         }
2055         
2056         JSCell* thingToCaseOn;
2057         if (allAreDirectCalls)
2058             thingToCaseOn = callLinkStatus[i].nonExecutableCallee();
2059         else {
2060             ASSERT(allAreClosureCalls);
2061             thingToCaseOn = callLinkStatus[i].executable();
2062         }
2063         data.cases.append(SwitchCase(m_graph.freeze(thingToCaseOn), calleeEntryBlock));
2064         VERBOSE_LOG("Finished inlining ", callLinkStatus[i], " at ", currentCodeOrigin(), ".\n");
2065     }
2066
2067     // Slow path block
2068     m_currentBlock = allocateUntargetableBlock();
2069     m_currentIndex = oldOffset;
2070     m_exitOK = true;
2071     data.fallThrough = BranchTarget(m_currentBlock);
2072     prepareToParseBlock();
2073     Node* myCallTargetNode = getDirect(calleeReg);
2074     if (couldTakeSlowPath) {
2075         addCall(
2076             resultOperand, callOp, nullptr, myCallTargetNode, argumentCountIncludingThis,
2077             registerOffset, prediction);
2078         VERBOSE_LOG("We added a call in the slow path\n");
2079     } else {
2080         addToGraph(CheckBadCell);
2081         addToGraph(Phantom, myCallTargetNode);
2082         emitArgumentPhantoms(registerOffset, argumentCountIncludingThis);
2083         
2084         set(VirtualRegister(resultOperand), addToGraph(BottomValue));
2085         VERBOSE_LOG("couldTakeSlowPath was false\n");
2086     }
2087
2088     m_currentIndex = nextOffset;
2089     m_exitOK = true; // Origin changed, so it's fine to exit again.
2090     processSetLocalQueue();
2091
2092     if (Node* terminal = m_currentBlock->terminal())
2093         ASSERT_UNUSED(terminal, terminal->op() == TailCall || terminal->op() == TailCallVarargs || terminal->op() == TailCallForwardVarargs);
2094     else {
2095         addJumpTo(continuationBlock);
2096     }
2097
2098     prepareToParseBlock();
2099     
2100     m_currentIndex = oldOffset;
2101     m_currentBlock = continuationBlock;
2102     m_exitOK = true;
2103     
2104     VERBOSE_LOG("Done inlining (hard).\nStack: ", currentCodeOrigin(), "\n");
2105     return true;
2106 }
2107
2108 template<typename ChecksFunctor>
2109 bool ByteCodeParser::handleMinMax(int resultOperand, NodeType op, int registerOffset, int argumentCountIncludingThis, const ChecksFunctor& insertChecks)
2110 {
2111     ASSERT(op == ArithMin || op == ArithMax);
2112
2113     if (argumentCountIncludingThis == 1) {
2114         insertChecks();
2115         double result = op == ArithMax ? -std::numeric_limits<double>::infinity() : +std::numeric_limits<double>::infinity();
2116         set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_graph.freeze(jsDoubleNumber(result)))));
2117         return true;
2118     }
2119      
2120     if (argumentCountIncludingThis == 2) {
2121         insertChecks();
2122         Node* result = get(VirtualRegister(virtualRegisterForArgument(1, registerOffset)));
2123         addToGraph(Phantom, Edge(result, NumberUse));
2124         set(VirtualRegister(resultOperand), result);
2125         return true;
2126     }
2127     
2128     if (argumentCountIncludingThis == 3) {
2129         insertChecks();
2130         set(VirtualRegister(resultOperand), addToGraph(op, get(virtualRegisterForArgument(1, registerOffset)), get(virtualRegisterForArgument(2, registerOffset))));
2131         return true;
2132     }
2133     
2134     // Don't handle >=3 arguments for now.
2135     return false;
2136 }
2137
2138 template<typename ChecksFunctor>
2139 bool ByteCodeParser::handleIntrinsicCall(Node* callee, int resultOperand, Intrinsic intrinsic, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction, const ChecksFunctor& insertChecks)
2140 {
2141     VERBOSE_LOG("       The intrinsic is ", intrinsic, "\n");
2142     
2143     // It so happens that the code below doesn't handle the invalid result case. We could fix that, but
2144     // it would only benefit intrinsics called as setters, like if you do:
2145     //
2146     //     o.__defineSetter__("foo", Math.pow)
2147     //
2148     // Which is extremely amusing, but probably not worth optimizing.
2149     if (!VirtualRegister(resultOperand).isValid())
2150         return false;
2151     
2152     switch (intrinsic) {
2153
2154     // Intrinsic Functions:
2155
2156     case AbsIntrinsic: {
2157         if (argumentCountIncludingThis == 1) { // Math.abs()
2158             insertChecks();
2159             set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantNaN)));
2160             return true;
2161         }
2162
2163         if (!MacroAssembler::supportsFloatingPointAbs())
2164             return false;
2165
2166         insertChecks();
2167         Node* node = addToGraph(ArithAbs, get(virtualRegisterForArgument(1, registerOffset)));
2168         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
2169             node->mergeFlags(NodeMayOverflowInt32InDFG);
2170         set(VirtualRegister(resultOperand), node);
2171         return true;
2172     }
2173
2174     case MinIntrinsic:
2175         return handleMinMax(resultOperand, ArithMin, registerOffset, argumentCountIncludingThis, insertChecks);
2176         
2177     case MaxIntrinsic:
2178         return handleMinMax(resultOperand, ArithMax, registerOffset, argumentCountIncludingThis, insertChecks);
2179
2180 #define DFG_ARITH_UNARY(capitalizedName, lowerName) \
2181     case capitalizedName##Intrinsic:
2182     FOR_EACH_DFG_ARITH_UNARY_OP(DFG_ARITH_UNARY)
2183 #undef DFG_ARITH_UNARY
2184     {
2185         if (argumentCountIncludingThis == 1) {
2186             insertChecks();
2187             set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantNaN)));
2188             return true;
2189         }
2190         Arith::UnaryType type = Arith::UnaryType::Sin;
2191         switch (intrinsic) {
2192 #define DFG_ARITH_UNARY(capitalizedName, lowerName) \
2193         case capitalizedName##Intrinsic: \
2194             type = Arith::UnaryType::capitalizedName; \
2195             break;
2196     FOR_EACH_DFG_ARITH_UNARY_OP(DFG_ARITH_UNARY)
2197 #undef DFG_ARITH_UNARY
2198         default:
2199             RELEASE_ASSERT_NOT_REACHED();
2200         }
2201         insertChecks();
2202         set(VirtualRegister(resultOperand), addToGraph(ArithUnary, OpInfo(static_cast<std::underlying_type<Arith::UnaryType>::type>(type)), get(virtualRegisterForArgument(1, registerOffset))));
2203         return true;
2204     }
2205
2206     case FRoundIntrinsic:
2207     case SqrtIntrinsic: {
2208         if (argumentCountIncludingThis == 1) {
2209             insertChecks();
2210             set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantNaN)));
2211             return true;
2212         }
2213
2214         NodeType nodeType = Unreachable;
2215         switch (intrinsic) {
2216         case FRoundIntrinsic:
2217             nodeType = ArithFRound;
2218             break;
2219         case SqrtIntrinsic:
2220             nodeType = ArithSqrt;
2221             break;
2222         default:
2223             RELEASE_ASSERT_NOT_REACHED();
2224         }
2225         insertChecks();
2226         set(VirtualRegister(resultOperand), addToGraph(nodeType, get(virtualRegisterForArgument(1, registerOffset))));
2227         return true;
2228     }
2229
2230     case PowIntrinsic: {
2231         if (argumentCountIncludingThis < 3) {
2232             // Math.pow() and Math.pow(x) return NaN.
2233             insertChecks();
2234             set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantNaN)));
2235             return true;
2236         }
2237         insertChecks();
2238         VirtualRegister xOperand = virtualRegisterForArgument(1, registerOffset);
2239         VirtualRegister yOperand = virtualRegisterForArgument(2, registerOffset);
2240         set(VirtualRegister(resultOperand), addToGraph(ArithPow, get(xOperand), get(yOperand)));
2241         return true;
2242     }
2243         
2244     case ArrayPushIntrinsic: {
2245 #if USE(JSVALUE32_64)
2246         if (isX86() || isMIPS()) {
2247             if (argumentCountIncludingThis > 2)
2248                 return false;
2249         }
2250 #endif
2251
2252         if (static_cast<unsigned>(argumentCountIncludingThis) >= MIN_SPARSE_ARRAY_INDEX)
2253             return false;
2254         
2255         ArrayMode arrayMode = getArrayMode(m_currentInstruction[OPCODE_LENGTH(op_call) - 2].u.arrayProfile);
2256         if (!arrayMode.isJSArray())
2257             return false;
2258         switch (arrayMode.type()) {
2259         case Array::Int32:
2260         case Array::Double:
2261         case Array::Contiguous:
2262         case Array::ArrayStorage: {
2263             insertChecks();
2264
2265             addVarArgChild(nullptr); // For storage.
2266             for (int i = 0; i < argumentCountIncludingThis; ++i)
2267                 addVarArgChild(get(virtualRegisterForArgument(i, registerOffset)));
2268             Node* arrayPush = addToGraph(Node::VarArg, ArrayPush, OpInfo(arrayMode.asWord()), OpInfo(prediction));
2269             set(VirtualRegister(resultOperand), arrayPush);
2270             
2271             return true;
2272         }
2273             
2274         default:
2275             return false;
2276         }
2277     }
2278
2279     case ArraySliceIntrinsic: {
2280 #if USE(JSVALUE32_64)
2281         if (isX86() || isMIPS()) {
2282             // There aren't enough registers for this to be done easily.
2283             return false;
2284         }
2285 #endif
2286         if (argumentCountIncludingThis < 2)
2287             return false;
2288
2289         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadConstantCache)
2290             || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache))
2291             return false;
2292
2293         ArrayMode arrayMode = getArrayMode(m_currentInstruction[OPCODE_LENGTH(op_call) - 2].u.arrayProfile);
2294         if (!arrayMode.isJSArray())
2295             return false;
2296
2297         if (arrayMode.arrayClass() != Array::OriginalArray)
2298             return false;
2299
2300         switch (arrayMode.type()) {
2301         case Array::Double:
2302         case Array::Int32:
2303         case Array::Contiguous: {
2304             JSGlobalObject* globalObject = m_graph.globalObjectFor(currentNodeOrigin().semantic);
2305
2306             Structure* arrayPrototypeStructure = globalObject->arrayPrototype()->structure();
2307             Structure* objectPrototypeStructure = globalObject->objectPrototype()->structure();
2308
2309             // FIXME: We could easily relax the Array/Object.prototype transition as long as we OSR exitted if we saw a hole.
2310             // https://bugs.webkit.org/show_bug.cgi?id=173171
2311             if (globalObject->arraySpeciesWatchpoint().state() == IsWatched
2312                 && globalObject->havingABadTimeWatchpoint()->isStillValid()
2313                 && arrayPrototypeStructure->transitionWatchpointSetIsStillValid()
2314                 && objectPrototypeStructure->transitionWatchpointSetIsStillValid()
2315                 && globalObject->arrayPrototypeChainIsSane()) {
2316
2317                 m_graph.watchpoints().addLazily(globalObject->arraySpeciesWatchpoint());
2318                 m_graph.watchpoints().addLazily(globalObject->havingABadTimeWatchpoint());
2319                 m_graph.registerAndWatchStructureTransition(arrayPrototypeStructure);
2320                 m_graph.registerAndWatchStructureTransition(objectPrototypeStructure);
2321
2322                 insertChecks();
2323
2324                 Node* array = get(virtualRegisterForArgument(0, registerOffset));
2325                 // We do a few things here to prove that we aren't skipping doing side-effects in an observable way:
2326                 // 1. We ensure that the "constructor" property hasn't been changed (because the observable
2327                 // effects of slice require that we perform a Get(array, "constructor") and we can skip
2328                 // that if we're an original array structure. (We can relax this in the future by using
2329                 // TryGetById and CheckCell).
2330                 //
2331                 // 2. We check that the array we're calling slice on has the same global object as the lexical
2332                 // global object that this code is running in. This requirement is necessary because we setup the
2333                 // watchpoints above on the lexical global object. This means that code that calls slice on
2334                 // arrays produced by other global objects won't get this optimization. We could relax this
2335                 // requirement in the future by checking that the watchpoint hasn't fired at runtime in the code
2336                 // we generate instead of registering it as a watchpoint that would invalidate the compilation.
2337                 //
2338                 // 3. By proving we're an original array structure, we guarantee that the incoming array
2339                 // isn't a subclass of Array.
2340
2341                 StructureSet structureSet;
2342                 structureSet.add(globalObject->originalArrayStructureForIndexingType(ArrayWithInt32));
2343                 structureSet.add(globalObject->originalArrayStructureForIndexingType(ArrayWithContiguous));
2344                 structureSet.add(globalObject->originalArrayStructureForIndexingType(ArrayWithDouble));
2345                 addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(structureSet)), array);
2346
2347                 addVarArgChild(array);
2348                 addVarArgChild(get(virtualRegisterForArgument(1, registerOffset))); // Start index.
2349                 if (argumentCountIncludingThis >= 3)
2350                     addVarArgChild(get(virtualRegisterForArgument(2, registerOffset))); // End index.
2351                 addVarArgChild(addToGraph(GetButterfly, array));
2352
2353                 Node* arraySlice = addToGraph(Node::VarArg, ArraySlice, OpInfo(), OpInfo());
2354                 set(VirtualRegister(resultOperand), arraySlice);
2355                 return true;
2356             }
2357
2358             return false;
2359         }
2360         default:
2361             return false;
2362         }
2363
2364         RELEASE_ASSERT_NOT_REACHED();
2365         return false;
2366     }
2367
2368     case ArrayIndexOfIntrinsic: {
2369         if (argumentCountIncludingThis < 2)
2370             return false;
2371
2372         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadIndexingType)
2373             || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadConstantCache)
2374             || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)
2375             || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
2376             return false;
2377
2378         ArrayMode arrayMode = getArrayMode(m_currentInstruction[OPCODE_LENGTH(op_call) - 2].u.arrayProfile);
2379         if (!arrayMode.isJSArray())
2380             return false;
2381
2382         if (arrayMode.arrayClass() != Array::OriginalArray)
2383             return false;
2384
2385         // We do not want to convert arrays into one type just to perform indexOf.
2386         if (arrayMode.doesConversion())
2387             return false;
2388
2389         switch (arrayMode.type()) {
2390         case Array::Double:
2391         case Array::Int32:
2392         case Array::Contiguous: {
2393             JSGlobalObject* globalObject = m_graph.globalObjectFor(currentNodeOrigin().semantic);
2394
2395             Structure* arrayPrototypeStructure = globalObject->arrayPrototype()->structure();
2396             Structure* objectPrototypeStructure = globalObject->objectPrototype()->structure();
2397
2398             // FIXME: We could easily relax the Array/Object.prototype transition as long as we OSR exitted if we saw a hole.
2399             // https://bugs.webkit.org/show_bug.cgi?id=173171
2400             if (globalObject->havingABadTimeWatchpoint()->isStillValid()
2401                 && arrayPrototypeStructure->transitionWatchpointSetIsStillValid()
2402                 && objectPrototypeStructure->transitionWatchpointSetIsStillValid()
2403                 && globalObject->arrayPrototypeChainIsSane()) {
2404
2405                 m_graph.watchpoints().addLazily(globalObject->havingABadTimeWatchpoint());
2406                 m_graph.registerAndWatchStructureTransition(arrayPrototypeStructure);
2407                 m_graph.registerAndWatchStructureTransition(objectPrototypeStructure);
2408
2409                 insertChecks();
2410
2411                 Node* array = get(virtualRegisterForArgument(0, registerOffset));
2412                 addVarArgChild(array);
2413                 addVarArgChild(get(virtualRegisterForArgument(1, registerOffset))); // Search element.
2414                 if (argumentCountIncludingThis >= 3)
2415                     addVarArgChild(get(virtualRegisterForArgument(2, registerOffset))); // Start index.
2416                 addVarArgChild(nullptr);
2417
2418                 Node* node = addToGraph(Node::VarArg, ArrayIndexOf, OpInfo(arrayMode.asWord()), OpInfo());
2419                 set(VirtualRegister(resultOperand), node);
2420                 return true;
2421             }
2422
2423             return false;
2424         }
2425         default:
2426             return false;
2427         }
2428
2429         RELEASE_ASSERT_NOT_REACHED();
2430         return false;
2431
2432     }
2433         
2434     case ArrayPopIntrinsic: {
2435         if (argumentCountIncludingThis != 1)
2436             return false;
2437         
2438         ArrayMode arrayMode = getArrayMode(m_currentInstruction[OPCODE_LENGTH(op_call) - 2].u.arrayProfile);
2439         if (!arrayMode.isJSArray())
2440             return false;
2441         switch (arrayMode.type()) {
2442         case Array::Int32:
2443         case Array::Double:
2444         case Array::Contiguous:
2445         case Array::ArrayStorage: {
2446             insertChecks();
2447             Node* arrayPop = addToGraph(ArrayPop, OpInfo(arrayMode.asWord()), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)));
2448             set(VirtualRegister(resultOperand), arrayPop);
2449             return true;
2450         }
2451             
2452         default:
2453             return false;
2454         }
2455     }
2456         
2457     case AtomicsAddIntrinsic:
2458     case AtomicsAndIntrinsic:
2459     case AtomicsCompareExchangeIntrinsic:
2460     case AtomicsExchangeIntrinsic:
2461     case AtomicsIsLockFreeIntrinsic:
2462     case AtomicsLoadIntrinsic:
2463     case AtomicsOrIntrinsic:
2464     case AtomicsStoreIntrinsic:
2465     case AtomicsSubIntrinsic:
2466     case AtomicsXorIntrinsic: {
2467         if (!is64Bit())
2468             return false;
2469         
2470         NodeType op = LastNodeType;
2471         unsigned numArgs = 0; // Number of actual args; we add one for the backing store pointer.
2472         switch (intrinsic) {
2473         case AtomicsAddIntrinsic:
2474             op = AtomicsAdd;
2475             numArgs = 3;
2476             break;
2477         case AtomicsAndIntrinsic:
2478             op = AtomicsAnd;
2479             numArgs = 3;
2480             break;
2481         case AtomicsCompareExchangeIntrinsic:
2482             op = AtomicsCompareExchange;
2483             numArgs = 4;
2484             break;
2485         case AtomicsExchangeIntrinsic:
2486             op = AtomicsExchange;
2487             numArgs = 3;
2488             break;
2489         case AtomicsIsLockFreeIntrinsic:
2490             // This gets no backing store, but we need no special logic for this since this also does
2491             // not need varargs.
2492             op = AtomicsIsLockFree;
2493             numArgs = 1;
2494             break;
2495         case AtomicsLoadIntrinsic:
2496             op = AtomicsLoad;
2497             numArgs = 2;
2498             break;
2499         case AtomicsOrIntrinsic:
2500             op = AtomicsOr;
2501             numArgs = 3;
2502             break;
2503         case AtomicsStoreIntrinsic:
2504             op = AtomicsStore;
2505             numArgs = 3;
2506             break;
2507         case AtomicsSubIntrinsic:
2508             op = AtomicsSub;
2509             numArgs = 3;
2510             break;
2511         case AtomicsXorIntrinsic:
2512             op = AtomicsXor;
2513             numArgs = 3;
2514             break;
2515         default:
2516             RELEASE_ASSERT_NOT_REACHED();
2517             break;
2518         }
2519         
2520         if (static_cast<unsigned>(argumentCountIncludingThis) < 1 + numArgs)
2521             return false;
2522         
2523         insertChecks();
2524         
2525         Vector<Node*, 3> args;
2526         for (unsigned i = 0; i < numArgs; ++i)
2527             args.append(get(virtualRegisterForArgument(1 + i, registerOffset)));
2528         
2529         Node* result;
2530         if (numArgs + 1 <= 3) {
2531             while (args.size() < 3)
2532                 args.append(nullptr);
2533             result = addToGraph(op, OpInfo(ArrayMode(Array::SelectUsingPredictions).asWord()), OpInfo(prediction), args[0], args[1], args[2]);
2534         } else {
2535             for (Node* node : args)
2536                 addVarArgChild(node);
2537             addVarArgChild(nullptr);
2538             result = addToGraph(Node::VarArg, op, OpInfo(ArrayMode(Array::SelectUsingPredictions).asWord()), OpInfo(prediction));
2539         }
2540         
2541         set(VirtualRegister(resultOperand), result);
2542         return true;
2543     }
2544
2545     case ParseIntIntrinsic: {
2546         if (argumentCountIncludingThis < 2)
2547             return false;
2548
2549         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell) || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
2550             return false;
2551
2552         insertChecks();
2553         VirtualRegister valueOperand = virtualRegisterForArgument(1, registerOffset);
2554         Node* parseInt;
2555         if (argumentCountIncludingThis == 2)
2556             parseInt = addToGraph(ParseInt, OpInfo(), OpInfo(prediction), get(valueOperand));
2557         else {
2558             ASSERT(argumentCountIncludingThis > 2);
2559             VirtualRegister radixOperand = virtualRegisterForArgument(2, registerOffset);
2560             parseInt = addToGraph(ParseInt, OpInfo(), OpInfo(prediction), get(valueOperand), get(radixOperand));
2561         }
2562         set(VirtualRegister(resultOperand), parseInt);
2563         return true;
2564     }
2565
2566     case CharCodeAtIntrinsic: {
2567         if (argumentCountIncludingThis != 2)
2568             return false;
2569
2570         insertChecks();
2571         VirtualRegister thisOperand = virtualRegisterForArgument(0, registerOffset);
2572         VirtualRegister indexOperand = virtualRegisterForArgument(1, registerOffset);
2573         Node* charCode = addToGraph(StringCharCodeAt, OpInfo(ArrayMode(Array::String).asWord()), get(thisOperand), get(indexOperand));
2574
2575         set(VirtualRegister(resultOperand), charCode);
2576         return true;
2577     }
2578
2579     case CharAtIntrinsic: {
2580         if (argumentCountIncludingThis != 2)
2581             return false;
2582
2583         insertChecks();
2584         VirtualRegister thisOperand = virtualRegisterForArgument(0, registerOffset);
2585         VirtualRegister indexOperand = virtualRegisterForArgument(1, registerOffset);
2586         Node* charCode = addToGraph(StringCharAt, OpInfo(ArrayMode(Array::String).asWord()), get(thisOperand), get(indexOperand));
2587
2588         set(VirtualRegister(resultOperand), charCode);
2589         return true;
2590     }
2591     case Clz32Intrinsic: {
2592         insertChecks();
2593         if (argumentCountIncludingThis == 1)
2594             set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_graph.freeze(jsNumber(32)))));
2595         else {
2596             Node* operand = get(virtualRegisterForArgument(1, registerOffset));
2597             set(VirtualRegister(resultOperand), addToGraph(ArithClz32, operand));
2598         }
2599         return true;
2600     }
2601     case FromCharCodeIntrinsic: {
2602         if (argumentCountIncludingThis != 2)
2603             return false;
2604
2605         insertChecks();
2606         VirtualRegister indexOperand = virtualRegisterForArgument(1, registerOffset);
2607         Node* charCode = addToGraph(StringFromCharCode, get(indexOperand));
2608
2609         set(VirtualRegister(resultOperand), charCode);
2610
2611         return true;
2612     }
2613
2614     case RegExpExecIntrinsic: {
2615         if (argumentCountIncludingThis != 2)
2616             return false;
2617         
2618         insertChecks();
2619         Node* regExpExec = addToGraph(RegExpExec, OpInfo(0), OpInfo(prediction), addToGraph(GetGlobalObject, callee), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)));
2620         set(VirtualRegister(resultOperand), regExpExec);
2621         
2622         return true;
2623     }
2624         
2625     case RegExpTestIntrinsic:
2626     case RegExpTestFastIntrinsic: {
2627         if (argumentCountIncludingThis != 2)
2628             return false;
2629
2630         if (intrinsic == RegExpTestIntrinsic) {
2631             // Don't inline intrinsic if we exited due to one of the primordial RegExp checks failing.
2632             if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell))
2633                 return false;
2634
2635             JSGlobalObject* globalObject = m_inlineStackTop->m_codeBlock->globalObject();
2636             Structure* regExpStructure = globalObject->regExpStructure();
2637             m_graph.registerStructure(regExpStructure);
2638             ASSERT(regExpStructure->storedPrototype().isObject());
2639             ASSERT(regExpStructure->storedPrototype().asCell()->classInfo(*m_vm) == RegExpPrototype::info());
2640
2641             FrozenValue* regExpPrototypeObjectValue = m_graph.freeze(regExpStructure->storedPrototype());
2642             Structure* regExpPrototypeStructure = regExpPrototypeObjectValue->structure();
2643
2644             auto isRegExpPropertySame = [&] (JSValue primordialProperty, UniquedStringImpl* propertyUID) {
2645                 JSValue currentProperty;
2646                 if (!m_graph.getRegExpPrototypeProperty(regExpStructure->storedPrototypeObject(), regExpPrototypeStructure, propertyUID, currentProperty))
2647                     return false;
2648                 
2649                 return currentProperty == primordialProperty;
2650             };
2651
2652             // Check that RegExp.exec is still the primordial RegExp.prototype.exec
2653             if (!isRegExpPropertySame(globalObject->regExpProtoExecFunction(), m_vm->propertyNames->exec.impl()))
2654                 return false;
2655
2656             // Check that regExpObject is actually a RegExp object.
2657             Node* regExpObject = get(virtualRegisterForArgument(0, registerOffset));
2658             addToGraph(Check, Edge(regExpObject, RegExpObjectUse));
2659
2660             // Check that regExpObject's exec is actually the primodial RegExp.prototype.exec.
2661             UniquedStringImpl* execPropertyID = m_vm->propertyNames->exec.impl();
2662             unsigned execIndex = m_graph.identifiers().ensure(execPropertyID);
2663             Node* actualProperty = addToGraph(TryGetById, OpInfo(execIndex), OpInfo(SpecFunction), Edge(regExpObject, CellUse));
2664             FrozenValue* regExpPrototypeExec = m_graph.freeze(globalObject->regExpProtoExecFunction());
2665             addToGraph(CheckCell, OpInfo(regExpPrototypeExec), Edge(actualProperty, CellUse));
2666         }
2667
2668         insertChecks();
2669         Node* regExpObject = get(virtualRegisterForArgument(0, registerOffset));
2670         Node* regExpExec = addToGraph(RegExpTest, OpInfo(0), OpInfo(prediction), addToGraph(GetGlobalObject, callee), regExpObject, get(virtualRegisterForArgument(1, registerOffset)));
2671         set(VirtualRegister(resultOperand), regExpExec);
2672         
2673         return true;
2674     }
2675
2676     case ObjectGetPrototypeOfIntrinsic: {
2677         if (argumentCountIncludingThis != 2)
2678             return false;
2679
2680         insertChecks();
2681         set(VirtualRegister(resultOperand), addToGraph(GetPrototypeOf, OpInfo(0), OpInfo(prediction), get(virtualRegisterForArgument(1, registerOffset))));
2682         return true;
2683     }
2684
2685     case ReflectGetPrototypeOfIntrinsic: {
2686         if (argumentCountIncludingThis != 2)
2687             return false;
2688
2689         insertChecks();
2690         set(VirtualRegister(resultOperand), addToGraph(GetPrototypeOf, OpInfo(0), OpInfo(prediction), Edge(get(virtualRegisterForArgument(1, registerOffset)), ObjectUse)));
2691         return true;
2692     }
2693
2694     case IsTypedArrayViewIntrinsic: {
2695         ASSERT(argumentCountIncludingThis == 2);
2696
2697         insertChecks();
2698         set(VirtualRegister(resultOperand), addToGraph(IsTypedArrayView, OpInfo(prediction), get(virtualRegisterForArgument(1, registerOffset))));
2699         return true;
2700     }
2701
2702     case StringPrototypeReplaceIntrinsic: {
2703         if (argumentCountIncludingThis != 3)
2704             return false;
2705
2706         // Don't inline intrinsic if we exited due to "search" not being a RegExp or String object.
2707         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
2708             return false;
2709
2710         // Don't inline intrinsic if we exited due to one of the primordial RegExp checks failing.
2711         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell))
2712             return false;
2713
2714         JSGlobalObject* globalObject = m_inlineStackTop->m_codeBlock->globalObject();
2715         Structure* regExpStructure = globalObject->regExpStructure();
2716         m_graph.registerStructure(regExpStructure);
2717         ASSERT(regExpStructure->storedPrototype().isObject());
2718         ASSERT(regExpStructure->storedPrototype().asCell()->classInfo(*m_vm) == RegExpPrototype::info());
2719
2720         FrozenValue* regExpPrototypeObjectValue = m_graph.freeze(regExpStructure->storedPrototype());
2721         Structure* regExpPrototypeStructure = regExpPrototypeObjectValue->structure();
2722
2723         auto isRegExpPropertySame = [&] (JSValue primordialProperty, UniquedStringImpl* propertyUID) {
2724             JSValue currentProperty;
2725             if (!m_graph.getRegExpPrototypeProperty(regExpStructure->storedPrototypeObject(), regExpPrototypeStructure, propertyUID, currentProperty))
2726                 return false;
2727
2728             return currentProperty == primordialProperty;
2729         };
2730
2731         // Check that searchRegExp.exec is still the primordial RegExp.prototype.exec
2732         if (!isRegExpPropertySame(globalObject->regExpProtoExecFunction(), m_vm->propertyNames->exec.impl()))
2733             return false;
2734
2735         // Check that searchRegExp.global is still the primordial RegExp.prototype.global
2736         if (!isRegExpPropertySame(globalObject->regExpProtoGlobalGetter(), m_vm->propertyNames->global.impl()))
2737             return false;
2738
2739         // Check that searchRegExp.unicode is still the primordial RegExp.prototype.unicode
2740         if (!isRegExpPropertySame(globalObject->regExpProtoUnicodeGetter(), m_vm->propertyNames->unicode.impl()))
2741             return false;
2742
2743         // Check that searchRegExp[Symbol.match] is still the primordial RegExp.prototype[Symbol.replace]
2744         if (!isRegExpPropertySame(globalObject->regExpProtoSymbolReplaceFunction(), m_vm->propertyNames->replaceSymbol.impl()))
2745             return false;
2746
2747         insertChecks();
2748
2749         Node* result = addToGraph(StringReplace, OpInfo(0), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)), get(virtualRegisterForArgument(2, registerOffset)));
2750         set(VirtualRegister(resultOperand), result);
2751         return true;
2752     }
2753         
2754     case StringPrototypeReplaceRegExpIntrinsic: {
2755         if (argumentCountIncludingThis != 3)
2756             return false;
2757         
2758         insertChecks();
2759         Node* result = addToGraph(StringReplaceRegExp, OpInfo(0), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)), get(virtualRegisterForArgument(2, registerOffset)));
2760         set(VirtualRegister(resultOperand), result);
2761         return true;
2762     }
2763         
2764     case RoundIntrinsic:
2765     case FloorIntrinsic:
2766     case CeilIntrinsic:
2767     case TruncIntrinsic: {
2768         if (argumentCountIncludingThis == 1) {
2769             insertChecks();
2770             set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantNaN)));
2771             return true;
2772         }
2773         insertChecks();
2774         Node* operand = get(virtualRegisterForArgument(1, registerOffset));
2775         NodeType op;
2776         if (intrinsic == RoundIntrinsic)
2777             op = ArithRound;
2778         else if (intrinsic == FloorIntrinsic)
2779             op = ArithFloor;
2780         else if (intrinsic == CeilIntrinsic)
2781             op = ArithCeil;
2782         else {
2783             ASSERT(intrinsic == TruncIntrinsic);
2784             op = ArithTrunc;
2785         }
2786         Node* roundNode = addToGraph(op, OpInfo(0), OpInfo(prediction), operand);
2787         set(VirtualRegister(resultOperand), roundNode);
2788         return true;
2789     }
2790     case IMulIntrinsic: {
2791         if (argumentCountIncludingThis != 3)
2792             return false;
2793         insertChecks();
2794         VirtualRegister leftOperand = virtualRegisterForArgument(1, registerOffset);
2795         VirtualRegister rightOperand = virtualRegisterForArgument(2, registerOffset);
2796         Node* left = get(leftOperand);
2797         Node* right = get(rightOperand);
2798         set(VirtualRegister(resultOperand), addToGraph(ArithIMul, left, right));
2799         return true;
2800     }
2801
2802     case RandomIntrinsic: {
2803         if (argumentCountIncludingThis != 1)
2804             return false;
2805         insertChecks();
2806         set(VirtualRegister(resultOperand), addToGraph(ArithRandom));
2807         return true;
2808     }
2809         
2810     case DFGTrueIntrinsic: {
2811         insertChecks();
2812         set(VirtualRegister(resultOperand), jsConstant(jsBoolean(true)));
2813         return true;
2814     }
2815         
2816     case OSRExitIntrinsic: {
2817         insertChecks();
2818         addToGraph(ForceOSRExit);
2819         set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantUndefined)));
2820         return true;
2821     }
2822         
2823     case IsFinalTierIntrinsic: {
2824         insertChecks();
2825         set(VirtualRegister(resultOperand),
2826             jsConstant(jsBoolean(Options::useFTLJIT() ? isFTL(m_graph.m_plan.mode) : true)));
2827         return true;
2828     }
2829         
2830     case SetInt32HeapPredictionIntrinsic: {
2831         insertChecks();
2832         for (int i = 1; i < argumentCountIncludingThis; ++i) {
2833             Node* node = get(virtualRegisterForArgument(i, registerOffset));
2834             if (node->hasHeapPrediction())
2835                 node->setHeapPrediction(SpecInt32Only);
2836         }
2837         set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantUndefined)));
2838         return true;
2839     }
2840         
2841     case CheckInt32Intrinsic: {
2842         insertChecks();
2843         for (int i = 1; i < argumentCountIncludingThis; ++i) {
2844             Node* node = get(virtualRegisterForArgument(i, registerOffset));
2845             addToGraph(Phantom, Edge(node, Int32Use));
2846         }
2847         set(VirtualRegister(resultOperand), jsConstant(jsBoolean(true)));
2848         return true;
2849     }
2850         
2851     case FiatInt52Intrinsic: {
2852         if (argumentCountIncludingThis != 2)
2853             return false;
2854         insertChecks();
2855         VirtualRegister operand = virtualRegisterForArgument(1, registerOffset);
2856         if (enableInt52())
2857             set(VirtualRegister(resultOperand), addToGraph(FiatInt52, get(operand)));
2858         else
2859             set(VirtualRegister(resultOperand), get(operand));
2860         return true;
2861     }
2862
2863     case JSMapGetIntrinsic: {
2864         if (argumentCountIncludingThis != 2)
2865             return false;
2866
2867         insertChecks();
2868         Node* map = get(virtualRegisterForArgument(0, registerOffset));
2869         Node* key = get(virtualRegisterForArgument(1, registerOffset));
2870         Node* hash = addToGraph(MapHash, key);
2871         Node* bucket = addToGraph(GetMapBucket, Edge(map, MapObjectUse), Edge(key), Edge(hash));
2872         Node* result = addToGraph(LoadValueFromMapBucket, OpInfo(), OpInfo(prediction), bucket);
2873         set(VirtualRegister(resultOperand), result);
2874         return true;
2875     }
2876
2877     case JSSetHasIntrinsic:
2878     case JSMapHasIntrinsic: {
2879         if (argumentCountIncludingThis != 2)
2880             return false;
2881
2882         insertChecks();
2883         Node* mapOrSet = get(virtualRegisterForArgument(0, registerOffset));
2884         Node* key = get(virtualRegisterForArgument(1, registerOffset));
2885         Node* hash = addToGraph(MapHash, key);
2886         UseKind useKind = intrinsic == JSSetHasIntrinsic ? SetObjectUse : MapObjectUse;
2887         Node* bucket = addToGraph(GetMapBucket, OpInfo(0), Edge(mapOrSet, useKind), Edge(key), Edge(hash));
2888         JSCell* sentinel = nullptr;
2889         if (intrinsic == JSMapHasIntrinsic)
2890             sentinel = m_vm->sentinelMapBucket.get();
2891         else
2892             sentinel = m_vm->sentinelSetBucket.get();
2893
2894         FrozenValue* frozenPointer = m_graph.freeze(sentinel);
2895         Node* invertedResult = addToGraph(CompareEqPtr, OpInfo(frozenPointer), bucket);
2896         Node* result = addToGraph(LogicalNot, invertedResult);
2897         set(VirtualRegister(resultOperand), result);
2898         return true;
2899     }
2900
2901     case JSSetBucketHeadIntrinsic:
2902     case JSMapBucketHeadIntrinsic: {
2903         ASSERT(argumentCountIncludingThis == 2);
2904
2905         insertChecks();
2906         Node* map = get(virtualRegisterForArgument(1, registerOffset));
2907         UseKind useKind = intrinsic == JSSetBucketHeadIntrinsic ? SetObjectUse : MapObjectUse;
2908         Node* result = addToGraph(GetMapBucketHead, Edge(map, useKind));
2909         set(VirtualRegister(resultOperand), result);
2910         return true;
2911     }
2912
2913     case JSSetBucketNextIntrinsic:
2914     case JSMapBucketNextIntrinsic: {
2915         ASSERT(argumentCountIncludingThis == 2);
2916
2917         insertChecks();
2918         Node* bucket = get(virtualRegisterForArgument(1, registerOffset));
2919         BucketOwnerType type = intrinsic == JSSetBucketNextIntrinsic ? BucketOwnerType::Set : BucketOwnerType::Map;
2920         Node* result = addToGraph(GetMapBucketNext, OpInfo(type), bucket);
2921         set(VirtualRegister(resultOperand), result);
2922         return true;
2923     }
2924
2925     case JSSetBucketKeyIntrinsic:
2926     case JSMapBucketKeyIntrinsic: {
2927         ASSERT(argumentCountIncludingThis == 2);
2928
2929         insertChecks();
2930         Node* bucket = get(virtualRegisterForArgument(1, registerOffset));
2931         Node* result = addToGraph(LoadKeyFromMapBucket, OpInfo(), OpInfo(prediction), bucket);
2932         set(VirtualRegister(resultOperand), result);
2933         return true;
2934     }
2935
2936     case JSMapBucketValueIntrinsic: {
2937         ASSERT(argumentCountIncludingThis == 2);
2938
2939         insertChecks();
2940         Node* bucket = get(virtualRegisterForArgument(1, registerOffset));
2941         Node* result = addToGraph(LoadValueFromMapBucket, OpInfo(), OpInfo(prediction), bucket);
2942         set(VirtualRegister(resultOperand), result);
2943         return true;
2944     }
2945
2946     case JSWeakMapGetIntrinsic: {
2947         if (argumentCountIncludingThis != 2)
2948             return false;
2949
2950         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
2951             return false;
2952
2953         insertChecks();
2954         Node* map = get(virtualRegisterForArgument(0, registerOffset));
2955         Node* key = get(virtualRegisterForArgument(1, registerOffset));
2956         Node* hash = addToGraph(MapHash, key);
2957         Node* result = addToGraph(WeakMapGet, OpInfo(), OpInfo(prediction), map, key, hash);
2958         set(VirtualRegister(resultOperand), result);
2959         return true;
2960     }
2961
2962     case HasOwnPropertyIntrinsic: {
2963         if (argumentCountIncludingThis != 2)
2964             return false;
2965
2966         // This can be racy, that's fine. We know that once we observe that this is created,
2967         // that it will never be destroyed until the VM is destroyed. It's unlikely that
2968         // we'd ever get to the point where we inline this as an intrinsic without the
2969         // cache being created, however, it's possible if we always throw exceptions inside
2970         // hasOwnProperty.
2971         if (!m_vm->hasOwnPropertyCache())
2972             return false;
2973
2974         insertChecks();
2975         Node* object = get(virtualRegisterForArgument(0, registerOffset));
2976         Node* key = get(virtualRegisterForArgument(1, registerOffset));
2977         Node* result = addToGraph(HasOwnProperty, object, key);
2978         set(VirtualRegister(resultOperand), result);
2979         return true;
2980     }
2981
2982     case StringPrototypeToLowerCaseIntrinsic: {
2983         if (argumentCountIncludingThis != 1)
2984             return false;
2985
2986         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
2987             return false;
2988
2989         insertChecks();
2990         Node* thisString = get(virtualRegisterForArgument(0, registerOffset));
2991         Node* result = addToGraph(ToLowerCase, thisString);
2992         set(VirtualRegister(resultOperand), result);
2993         return true;
2994     }
2995
2996     case NumberPrototypeToStringIntrinsic: {
2997         if (argumentCountIncludingThis != 1 && argumentCountIncludingThis != 2)
2998             return false;
2999
3000         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
3001             return false;
3002
3003         insertChecks();
3004         Node* thisNumber = get(virtualRegisterForArgument(0, registerOffset));
3005         if (argumentCountIncludingThis == 1) {
3006             Node* result = addToGraph(ToString, thisNumber);
3007             set(VirtualRegister(resultOperand), result);
3008         } else {
3009             Node* radix = get(virtualRegisterForArgument(1, registerOffset));
3010             Node* result = addToGraph(NumberToStringWithRadix, thisNumber, radix);
3011             set(VirtualRegister(resultOperand), result);
3012         }
3013         return true;
3014     }
3015
3016     default:
3017         return false;
3018     }
3019 }
3020
3021 template<typename ChecksFunctor>
3022 bool ByteCodeParser::handleDOMJITCall(Node* callTarget, int resultOperand, const DOMJIT::Signature* signature, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction, const ChecksFunctor& insertChecks)
3023 {
3024     if (argumentCountIncludingThis != static_cast<int>(1 + signature->argumentCount))
3025         return false;
3026     if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
3027         return false;
3028
3029     // FIXME: Currently, we only support functions which arguments are up to 2.
3030     // Eventually, we should extend this. But possibly, 2 or 3 can cover typical use cases.
3031     // https://bugs.webkit.org/show_bug.cgi?id=164346
3032     ASSERT_WITH_MESSAGE(argumentCountIncludingThis <= JSC_DOMJIT_SIGNATURE_MAX_ARGUMENTS_INCLUDING_THIS, "Currently CallDOM does not support an arbitrary length arguments.");
3033
3034     insertChecks();
3035     addCall(resultOperand, Call, signature, callTarget, argumentCountIncludingThis, registerOffset, prediction);
3036     return true;
3037 }
3038
3039
3040 template<typename ChecksFunctor>
3041 bool ByteCodeParser::handleIntrinsicGetter(int resultOperand, SpeculatedType prediction, const GetByIdVariant& variant, Node* thisNode, const ChecksFunctor& insertChecks)
3042 {
3043     switch (variant.intrinsic()) {
3044     case TypedArrayByteLengthIntrinsic: {
3045         insertChecks();
3046
3047         TypedArrayType type = (*variant.structureSet().begin())->classInfo()->typedArrayStorageType;
3048         Array::Type arrayType = toArrayType(type);
3049         size_t logSize = logElementSize(type);
3050
3051         variant.structureSet().forEach([&] (Structure* structure) {
3052             TypedArrayType curType = structure->classInfo()->typedArrayStorageType;
3053             ASSERT(logSize == logElementSize(curType));
3054             arrayType = refineTypedArrayType(arrayType, curType);
3055             ASSERT(arrayType != Array::Generic);
3056         });
3057
3058         Node* lengthNode = addToGraph(GetArrayLength, OpInfo(ArrayMode(arrayType).asWord()), thisNode);
3059
3060         if (!logSize) {
3061             set(VirtualRegister(resultOperand), lengthNode);
3062             return true;
3063         }
3064
3065         // We can use a BitLShift here because typed arrays will never have a byteLength
3066         // that overflows int32.
3067         Node* shiftNode = jsConstant(jsNumber(logSize));
3068         set(VirtualRegister(resultOperand), addToGraph(BitLShift, lengthNode, shiftNode));
3069
3070         return true;
3071     }
3072
3073     case TypedArrayLengthIntrinsic: {
3074         insertChecks();
3075
3076         TypedArrayType type = (*variant.structureSet().begin())->classInfo()->typedArrayStorageType;
3077         Array::Type arrayType = toArrayType(type);
3078
3079         variant.structureSet().forEach([&] (Structure* structure) {
3080             TypedArrayType curType = structure->classInfo()->typedArrayStorageType;
3081             arrayType = refineTypedArrayType(arrayType, curType);
3082             ASSERT(arrayType != Array::Generic);
3083         });
3084
3085         set(VirtualRegister(resultOperand), addToGraph(GetArrayLength, OpInfo(ArrayMode(arrayType).asWord()), thisNode));
3086
3087         return true;
3088
3089     }
3090
3091     case TypedArrayByteOffsetIntrinsic: {
3092         insertChecks();
3093
3094         TypedArrayType type = (*variant.structureSet().begin())->classInfo()->typedArrayStorageType;
3095         Array::Type arrayType = toArrayType(type);
3096
3097         variant.structureSet().forEach([&] (Structure* structure) {
3098             TypedArrayType curType = structure->classInfo()->typedArrayStorageType;
3099             arrayType = refineTypedArrayType(arrayType, curType);
3100             ASSERT(arrayType != Array::Generic);
3101         });
3102
3103         set(VirtualRegister(resultOperand), addToGraph(GetTypedArrayByteOffset, OpInfo(ArrayMode(arrayType).asWord()), thisNode));
3104
3105         return true;
3106     }
3107
3108     case UnderscoreProtoIntrinsic: {
3109         insertChecks();
3110
3111         bool canFold = !variant.structureSet().isEmpty();
3112         JSValue prototype;
3113         variant.structureSet().forEach([&] (Structure* structure) {
3114             auto getPrototypeMethod = structure->classInfo()->methodTable.getPrototype;
3115             MethodTable::GetPrototypeFunctionPtr defaultGetPrototype = JSObject::getPrototype;
3116             if (getPrototypeMethod != defaultGetPrototype) {
3117                 canFold = false;
3118                 return;
3119             }
3120
3121             if (structure->hasPolyProto()) {
3122                 canFold = false;
3123                 return;
3124             }
3125             if (!prototype)
3126                 prototype = structure->storedPrototype();
3127             else if (prototype != structure->storedPrototype())
3128                 canFold = false;
3129         });
3130
3131         // OK, only one prototype is found. We perform constant folding here.
3132         // This information is important for super's constructor call to get new.target constant.
3133         if (prototype && canFold) {
3134             set(VirtualRegister(resultOperand), weakJSConstant(prototype));
3135             return true;
3136         }
3137
3138         set(VirtualRegister(resultOperand), addToGraph(GetPrototypeOf, OpInfo(0), OpInfo(prediction), thisNode));
3139         return true;
3140     }
3141
3142     default:
3143         return false;
3144     }
3145     RELEASE_ASSERT_NOT_REACHED();
3146 }
3147
3148 static void blessCallDOMGetter(Node* node)
3149 {
3150     DOMJIT::CallDOMGetterSnippet* snippet = node->callDOMGetterData()->snippet;
3151     if (snippet && !snippet->effect.mustGenerate())
3152         node->clearFlags(NodeMustGenerate);
3153 }
3154
3155 bool ByteCodeParser::handleDOMJITGetter(int resultOperand, const GetByIdVariant& variant, Node* thisNode, unsigned identifierNumber, SpeculatedType prediction)
3156 {
3157     if (!variant.domAttribute())
3158         return false;
3159
3160     auto domAttribute = variant.domAttribute().value();
3161
3162     // We do not need to actually look up CustomGetterSetter here. Checking Structures or registering watchpoints are enough,
3163     // since replacement of CustomGetterSetter always incurs Structure transition.
3164     if (!check(variant.conditionSet()))
3165         return false;
3166     addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.structureSet())), thisNode);
3167
3168     // We do not need to emit CheckCell thingy here. When the custom accessor is replaced to different one, Structure transition occurs.
3169     addToGraph(CheckSubClass, OpInfo(domAttribute.classInfo), thisNode);
3170
3171     CallDOMGetterData* callDOMGetterData = m_graph.m_callDOMGetterData.add();
3172     callDOMGetterData->customAccessorGetter = variant.customAccessorGetter();
3173     ASSERT(callDOMGetterData->customAccessorGetter);
3174
3175     if (const auto* domJIT = domAttribute.domJIT) {
3176         callDOMGetterData->domJIT = domJIT;
3177         Ref<DOMJIT::CallDOMGetterSnippet> snippet = domJIT->compiler()();
3178         callDOMGetterData->snippet = snippet.ptr();
3179         m_graph.m_domJITSnippets.append(WTFMove(snippet));
3180     }
3181     DOMJIT::CallDOMGetterSnippet* callDOMGetterSnippet = callDOMGetterData->snippet;
3182     callDOMGetterData->identifierNumber = identifierNumber;
3183
3184     Node* callDOMGetterNode = nullptr;
3185     // GlobalObject of thisNode is always used to create a DOMWrapper.
3186     if (callDOMGetterSnippet && callDOMGetterSnippet->requireGlobalObject) {
3187         Node* globalObject = addToGraph(GetGlobalObject, thisNode);
3188         callDOMGetterNode = addToGraph(CallDOMGetter, OpInfo(callDOMGetterData), OpInfo(prediction), thisNode, globalObject);
3189     } else
3190         callDOMGetterNode = addToGraph(CallDOMGetter, OpInfo(callDOMGetterData), OpInfo(prediction), thisNode);
3191     blessCallDOMGetter(callDOMGetterNode);
3192     set(VirtualRegister(resultOperand), callDOMGetterNode);
3193     return true;
3194 }
3195
3196 bool ByteCodeParser::handleModuleNamespaceLoad(int resultOperand, SpeculatedType prediction, Node* base, GetByIdStatus getById)
3197 {
3198     if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell))
3199         return false;
3200     addToGraph(CheckCell, OpInfo(m_graph.freeze(getById.moduleNamespaceObject())), Edge(base, CellUse));
3201
3202     // Ideally we wouldn't have to do this Phantom. But:
3203     //
3204     // For the constant case: we must do it because otherwise we would have no way of knowing
3205     // that the scope is live at OSR here.
3206     //
3207     // For the non-constant case: GetClosureVar could be DCE'd, but baseline's implementation
3208     // won't be able to handle an Undefined scope.
3209     addToGraph(Phantom, base);
3210
3211     // Constant folding in the bytecode parser is important for performance. This may not
3212     // have executed yet. If it hasn't, then we won't have a prediction. Lacking a
3213     // prediction, we'd otherwise think that it has to exit. Then when it did execute, we
3214     // would recompile. But if we can fold it here, we avoid the exit.
3215     m_graph.freeze(getById.moduleEnvironment());
3216     if (JSValue value = m_graph.tryGetConstantClosureVar(getById.moduleEnvironment(), getById.scopeOffset())) {
3217         set(VirtualRegister(resultOperand), weakJSConstant(value));
3218         return true;
3219     }
3220     set(VirtualRegister(resultOperand), addToGraph(GetClosureVar, OpInfo(getById.scopeOffset().offset()), OpInfo(prediction), weakJSConstant(getById.moduleEnvironment())));
3221     return true;
3222 }
3223
3224 template<typename ChecksFunctor>
3225 bool ByteCodeParser::handleTypedArrayConstructor(
3226     int resultOperand, InternalFunction* function, int registerOffset,
3227     int argumentCountIncludingThis, TypedArrayType type, const ChecksFunctor& insertChecks)
3228 {
3229     if (!isTypedView(type))
3230         return false;
3231     
3232     if (function->classInfo() != constructorClassInfoForType(type))
3233         return false;
3234     
3235     if (function->globalObject() != m_inlineStackTop->m_codeBlock->globalObject())
3236         return false;
3237     
3238     // We only have an intrinsic for the case where you say:
3239     //
3240     // new FooArray(blah);
3241     //
3242     // Of course, 'blah' could be any of the following:
3243     //
3244     // - Integer, indicating that you want to allocate an array of that length.
3245     //   This is the thing we're hoping for, and what we can actually do meaningful
3246     //   optimizations for.
3247     //
3248     // - Array buffer, indicating that you want to create a view onto that _entire_
3249     //   buffer.
3250     //
3251     // - Non-buffer object, indicating that you want to create a copy of that
3252     //   object by pretending that it quacks like an array.
3253     //
3254     // - Anything else, indicating that you want to have an exception thrown at
3255     //   you.
3256     //
3257     // The intrinsic, NewTypedArray, will behave as if it could do any of these
3258     // things up until we do Fixup. Thereafter, if child1 (i.e. 'blah') is
3259     // predicted Int32, then we lock it in as a normal typed array allocation.
3260     // Otherwise, NewTypedArray turns into a totally opaque function call that
3261     // may clobber the world - by virtue of it accessing properties on what could
3262     // be an object.
3263     //
3264     // Note that although the generic form of NewTypedArray sounds sort of awful,
3265     // it is actually quite likely to be more efficient than a fully generic
3266     // Construct. So, we might want to think about making NewTypedArray variadic,
3267     // or else making Construct not super slow.
3268     
3269     if (argumentCountIncludingThis != 2)
3270         return false;
3271     
3272     if (!function->globalObject()->typedArrayStructureConcurrently(type))
3273         return false;
3274
3275     insertChecks();
3276     set(VirtualRegister(resultOperand),
3277         addToGraph(NewTypedArray, OpInfo(type), get(virtualRegisterForArgument(1, registerOffset))));
3278     return true;
3279 }
3280
3281 template<typename ChecksFunctor>
3282 bool ByteCodeParser::handleConstantInternalFunction(
3283     Node* callTargetNode, int resultOperand, InternalFunction* function, int registerOffset,
3284     int argumentCountIncludingThis, CodeSpecializationKind kind, SpeculatedType prediction, const ChecksFunctor& insertChecks)
3285 {
3286     VERBOSE_LOG("    Handling constant internal function ", JSValue(function), "\n");
3287     
3288     // It so happens that the code below assumes that the result operand is valid. It's extremely
3289     // unlikely that the result operand would be invalid - you'd have to call this via a setter call.
3290     if (!VirtualRegister(resultOperand).isValid())
3291         return false;
3292
3293     if (kind == CodeForConstruct) {
3294         Node* newTargetNode = get(virtualRegisterForArgument(0, registerOffset));
3295         // We cannot handle the case where new.target != callee (i.e. a construct from a super call) because we
3296         // don't know what the prototype of the constructed object will be.
3297         // FIXME: If we have inlined super calls up to the call site, however, we should be able to figure out the structure. https://bugs.webkit.org/show_bug.cgi?id=152700
3298         if (newTargetNode != callTargetNode)
3299             return false;
3300     }
3301
3302     if (function->classInfo() == ArrayConstructor::info()) {
3303         if (function->globalObject() != m_inlineStackTop->m_codeBlock->globalObject())
3304             return false;
3305         
3306         insertChecks();
3307         if (argumentCountIncludingThis == 2) {
3308             set(VirtualRegister(resultOperand),
3309                 addToGraph(NewArrayWithSize, OpInfo(ArrayWithUndecided), get(virtualRegisterForArgument(1, registerOffset))));
3310             return true;
3311         }
3312         
3313         for (int i = 1; i < argumentCountIncludingThis; ++i)
3314             addVarArgChild(get(virtualRegisterForArgument(i, registerOffset)));
3315         set(VirtualRegister(resultOperand),
3316             addToGraph(Node::VarArg, NewArray, OpInfo(ArrayWithUndecided), OpInfo(0)));
3317         return true;
3318     }
3319
3320     if (function->classInfo() == NumberConstructor::info()) {
3321         if (kind == CodeForConstruct)
3322             return false;
3323
3324         insertChecks();
3325         if (argumentCountIncludingThis <= 1)
3326             set(VirtualRegister(resultOperand), jsConstant(jsNumber(0)));
3327         else
3328             set(VirtualRegister(resultOperand), addToGraph(ToNumber, OpInfo(0), OpInfo(prediction), get(virtualRegisterForArgument(1, registerOffset))));
3329
3330         return true;
3331     }
3332     
3333     if (function->classInfo() == StringConstructor::info()) {
3334         insertChecks();
3335         
3336         Node* result;
3337         
3338         if (argumentCountIncludingThis <= 1)
3339             result = jsConstant(m_vm->smallStrings.emptyString());
3340         else
3341             result = addToGraph(CallStringConstructor, get(virtualRegisterForArgument(1, registerOffset)));
3342         
3343         if (kind == CodeForConstruct)
3344             result = addToGraph(NewStringObject, OpInfo(m_graph.registerStructure(function->globalObject()->stringObjectStructure())), result);
3345         
3346         set(VirtualRegister(resultOperand), result);
3347         return true;
3348     }
3349
3350     // FIXME: This should handle construction as well. https://bugs.webkit.org/show_bug.cgi?id=155591
3351     if (function->classInfo() == ObjectConstructor::info() && kind == CodeForCall) {
3352         insertChecks();
3353
3354         Node* result;
3355         if (argumentCountIncludingThis <= 1)
3356             result = addToGraph(NewObject, OpInfo(m_graph.registerStructure(function->globalObject()->objectStructureForObjectConstructor())));
3357         else
3358             result = addToGraph(CallObjectConstructor, get(virtualRegisterForArgument(1, registerOffset)));
3359         set(VirtualRegister(resultOperand), result);
3360         return true;
3361     }
3362
3363     for (unsigned typeIndex = 0; typeIndex < NUMBER_OF_TYPED_ARRAY_TYPES; ++typeIndex) {
3364         bool result = handleTypedArrayConstructor(
3365             resultOperand, function, registerOffset, argumentCountIncludingThis,
3366             indexToTypedArrayType(typeIndex), insertChecks);
3367         if (result)
3368             return true;
3369     }
3370     
3371     return false;
3372 }
3373
3374 Node* ByteCodeParser::handleGetByOffset(
3375     SpeculatedType prediction, Node* base, unsigned identifierNumber, PropertyOffset offset,
3376     const InferredType::Descriptor& inferredType, NodeType op)
3377 {
3378     Node* propertyStorage;
3379     if (isInlineOffset(offset))
3380         propertyStorage = base;
3381     else
3382         propertyStorage = addToGraph(GetButterfly, base);
3383     
3384     StorageAccessData* data = m_graph.m_storageAccessData.add();
3385     data->offset = offset;
3386     data->identifierNumber = identifierNumber;
3387     data->inferredType = inferredType;
3388     m_graph.registerInferredType(inferredType);
3389     
3390     Node* getByOffset = addToGraph(op, OpInfo(data), OpInfo(prediction), propertyStorage, base);
3391
3392     return getByOffset;
3393 }
3394
3395 Node* ByteCodeParser::handlePutByOffset(
3396     Node* base, unsigned identifier, PropertyOffset offset, const InferredType::Descriptor& inferredType,
3397     Node* value)
3398 {
3399     Node* propertyStorage;
3400     if (isInlineOffset(offset))
3401         propertyStorage = base;
3402     else
3403         propertyStorage = addToGraph(GetButterfly, base);
3404     
3405     StorageAccessData* data = m_graph.m_storageAccessData.add();
3406     data->offset = offset;
3407     data->identifierNumber = identifier;
3408     data->inferredType = inferredType;
3409     m_graph.registerInferredType(inferredType);
3410     
3411     Node* result = addToGraph(PutByOffset, OpInfo(data), propertyStorage, base, value);
3412     
3413     return result;
3414 }
3415
3416 bool ByteCodeParser::check(const ObjectPropertyCondition& condition)
3417 {
3418     if (!condition)
3419         return false;
3420     
3421     if (m_graph.watchCondition(condition))
3422         return true;
3423     
3424     Structure* structure = condition.object()->structure();
3425     if (!condition.structureEnsuresValidity(structure))
3426         return false;
3427     
3428     addToGraph(
3429         CheckStructure,
3430         OpInfo(m_graph.addStructureSet(structure)),
3431         weakJSConstant(condition.object()));
3432     return true;
3433 }
3434
3435 GetByOffsetMethod ByteCodeParser::promoteToConstant(GetByOffsetMethod method)
3436 {
3437     if (method.kind() == GetByOffsetMethod::LoadFromPrototype
3438         && method.prototype()->structure()->dfgShouldWatch()) {
3439         if (JSValue constant = m_graph.tryGetConstantProperty(method.prototype()->value(), method.prototype()->structure(), method.offset()))
3440             return GetByOffsetMethod::constant(m_graph.freeze(constant));
3441     }
3442     
3443     return method;
3444 }
3445
3446 bool ByteCodeParser::needsDynamicLookup(ResolveType type, OpcodeID opcode)
3447 {
3448     ASSERT(opcode == op_resolve_scope || opcode == op_get_from_scope || opcode == op_put_to_scope);
3449
3450     JSGlobalObject* globalObject = m_inlineStackTop->m_codeBlock->globalObject();
3451     if (needsVarInjectionChecks(type) && globalObject->varInjectionWatchpoint()->hasBeenInvalidated())
3452         return true;
3453
3454     switch (type) {
3455     case GlobalProperty:
3456     case GlobalVar:
3457     case GlobalLexicalVar:
3458     case ClosureVar:
3459     case LocalClosureVar:
3460     case ModuleVar:
3461         return false;
3462
3463     case UnresolvedProperty:
3464     case UnresolvedPropertyWithVarInjectionChecks: {
3465         // The heuristic for UnresolvedProperty scope accesses is we will ForceOSRExit if we
3466         // haven't exited from from this access before to let the baseline JIT try to better
3467         // cache the access. If we've already exited from this operation, it's unlikely that
3468         // the baseline will come up with a better ResolveType and instead we will compile
3469         // this as a dynamic scope access.
3470
3471         // We only track our heuristic through resolve_scope since resolve_scope will
3472         // dominate unresolved gets/puts on that scope.
3473         if (opcode != op_resolve_scope)
3474             return true;
3475
3476         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, InadequateCoverage)) {
3477             // We've already exited so give up on getting better ResolveType information.
3478             return true;
3479         }
3480
3481         // We have not exited yet, so let's have the baseline get better ResolveType information for us.
3482         // This type of code is often seen when we tier up in a loop but haven't executed the part
3483         // of a function that comes after the loop.
3484         return false;
3485     }
3486
3487     case Dynamic:
3488         return true;
3489
3490     case GlobalPropertyWithVarInjectionChecks:
3491     case GlobalVarWithVarInjectionChecks:
3492     case GlobalLexicalVarWithVarInjectionChecks:
3493     case ClosureVarWithVarInjectionChecks:
3494         return false;
3495     }
3496
3497     ASSERT_NOT_REACHED();
3498     return false;
3499 }
3500
3501 GetByOffsetMethod ByteCodeParser::planLoad(const ObjectPropertyCondition& condition)
3502 {
3503     VERBOSE_LOG("Planning a load: ", condition, "\n");
3504     
3505     // We might promote this to Equivalence, and a later DFG pass might also do such promotion
3506     // even if we fail, but for simplicity this cannot be asked to load an equivalence condition.
3507     // None of the clients of this method will request a load of an Equivalence condition anyway,
3508     // and supporting it would complicate the heuristics below.
3509     RELEASE_ASSERT(condition.kind() == PropertyCondition::Presence);
3510     
3511     // Here's the ranking of how to handle this, from most preferred to least preferred:
3512     //
3513     // 1) Watchpoint on an equivalence condition and return a constant node for the loaded value.
3514     //    No other code is emitted, and the structure of the base object is never registered.
3515     //    Hence this results in zero code and we won't jettison this compilation if the object
3516     //    transitions, even if the structure is watchable right now.
3517     //
3518     // 2) Need to emit a load, and the current structure of the base is going to be watched by the
3519     //    DFG anyway (i.e. dfgShouldWatch). Watch the structure and emit the load. Don't watch the
3520     //    condition, since the act of turning the base into a constant in IR will cause the DFG to
3521     //    watch the structure anyway and doing so would subsume watching the condition.
3522     //
3523     // 3) Need to emit a load, and the current structure of the base is watchable but not by the
3524     //    DFG (i.e. transitionWatchpointSetIsStillValid() and !dfgShouldWatchIfPossible()). Watch
3525     //    the condition, and emit a load.
3526     //
3527     // 4) Need to emit a load, and the current structure of the base is not watchable. Emit a
3528     //    structure check, and emit a load.
3529     //
3530     // 5) The condition does not hold. Give up and return null.
3531     
3532     // First, try to promote Presence to Equivalence. We do this before doing anything else
3533     // because it's the most profitable. Also, there are cases where the presence is watchable but
3534     // we don't want to watch it unless it became an equivalence (see the relationship between
3535     // (1), (2), and (3) above).
3536     ObjectPropertyCondition equivalenceCondition = condition.attemptToMakeEquivalenceWithoutBarrier(*m_vm);
3537     if (m_graph.watchCondition(equivalenceCondition))
3538         return GetByOffsetMethod::constant(m_graph.freeze(equivalenceCondition.requiredValue()));
3539     
3540     // At this point, we'll have to materialize the condition's base as a constant in DFG IR. Once
3541     // we do this, the frozen value will have its own idea of what the structure is. Use that from
3542     // now on just because it's less confusing.
3543     FrozenValue* base = m_graph.freeze(condition.object());
3544     Structure* structure = base->structure();
3545     
3546     // Check if the structure that we've registered makes the condition hold. If not, just give
3547     // up. This is case (5) above.
3548     if (!condition.structureEnsuresValidity(structure))
3549         return GetByOffsetMethod();
3550     
3551     // If the structure is watched by the DFG already, then just use this fact to emit the load.
3552     // This is case (2) above.
3553     if (structure->dfgShouldWatch())
3554         return promoteToConstant(GetByOffsetMethod::loadFromPrototype(base, condition.offset()));
3555     
3556     // If we can watch the condition right now, then we can emit the load after watching it. This
3557     // is case (3) above.
3558     if (m_graph.watchCondition(condition))
3559         return promoteToConstant(GetByOffsetMethod::loadFromPrototype(base, condition.offset()));
3560     
3561     // We can't watch anything but we know that the current structure satisfies the condition. So,
3562     // check for that structure and then emit the load.
3563     addToGraph(
3564         CheckStructure, 
3565         OpInfo(m_graph.addStructureSet(structure)),
3566         addToGraph(JSConstant, OpInfo(base)));
3567     return promoteToConstant(GetByOffsetMethod::loadFromPrototype(base, condition.offset()));
3568 }
3569
3570 Node* ByteCodeParser::load(
3571     SpeculatedType prediction, unsigned identifierNumber, const GetByOffsetMethod& method,
3572     NodeType op)
3573 {
3574     switch (method.kind()) {
3575     case GetByOffsetMethod::Invalid:
3576         return nullptr;
3577     case GetByOffsetMethod::Constant:
3578         return addToGraph(JSConstant, OpInfo(method.constant()));
3579     case GetByOffsetMethod::LoadFromPrototype: {
3580         Node* baseNode = addToGraph(JSConstant, OpInfo(method.prototype()));
3581         return handleGetByOffset(
3582             prediction, baseNode, identifierNumber, method.offset(), InferredType::Top, op);
3583     }
3584     case GetByOffsetMethod::Load:
3585         // Will never see this from planLoad().
3586         RELEASE_ASSERT_NOT_REACHED();
3587         return nullptr;
3588     }
3589     
3590     RELEASE_ASSERT_NOT_REACHED();
3591     return nullptr;
3592 }
3593
3594 Node* ByteCodeParser::load(
3595     SpeculatedType prediction, const ObjectPropertyCondition& condition, NodeType op)
3596 {
3597     GetByOffsetMethod method = planLoad(condition);
3598     return load(prediction, m_graph.identifiers().ensure(condition.uid()), method, op);
3599 }
3600
3601 bool ByteCodeParser::check(const ObjectPropertyConditionSet& conditionSet)
3602 {
3603     for (const ObjectPropertyCondition& condition : conditionSet) {
3604         if (!check(condition))
3605             return false;
3606     }
3607     return true;
3608 }
3609
3610 GetByOffsetMethod ByteCodeParser::planLoad(const ObjectPropertyConditionSet& conditionSet)
3611 {
3612     VERBOSE_LOG("conditionSet = ", conditionSet, "\n");
3613     
3614     GetByOffsetMethod result;
3615     for (const ObjectPropertyCondition& condition : conditionSet) {
3616         switch (condition.kind()) {
3617         case PropertyCondition::Presence:
3618             RELEASE_ASSERT(!result); // Should only see exactly one of these.
3619             result = planLoad(condition);
3620             if (!result)
3621                 return GetByOffsetMethod();
3622             break;
3623         default:
3624             if (!check(condition))
3625                 return GetByOffsetMethod();
3626             break;
3627         }
3628     }
3629     if (!result) {
3630         // We have a unset property.
3631         ASSERT(!conditionSet.numberOfConditionsWithKind(PropertyCondition::Presence));
3632         return GetByOffsetMethod::constant(m_constantUndefined);
3633     }
3634     return result;
3635 }
3636
3637 Node* ByteCodeParser::load(
3638     SpeculatedType prediction, const ObjectPropertyConditionSet& conditionSet, NodeType op)
3639 {
3640     GetByOffsetMethod method = planLoad(conditionSet);
3641     return load(
3642         prediction,