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