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