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